/* * Copyright (c) 2015 Jonas Kalderstam. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.nononsenseapps.notepad.ui.settings; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.SwitchPreference; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; import com.nononsenseapps.build.Config; import com.nononsenseapps.filepicker.FilePickerActivity; import com.nononsenseapps.notepad.BuildConfig; import com.nononsenseapps.notepad.R; import com.nononsenseapps.notepad.data.local.orgmode.SDSynchronizer; import com.nononsenseapps.notepad.data.remote.orgmodedropbox.DropboxSyncHelper; import com.nononsenseapps.notepad.data.remote.orgmodedropbox.DropboxSynchronizer; import com.nononsenseapps.notepad.data.service.OrgSyncService; import com.nononsenseapps.notepad.ui.common.DialogGoogleAccount; import com.nononsenseapps.notepad.ui.common.DialogPasswordSettings; import com.nononsenseapps.notepad.ui.orgmodedropbox.DropboxFilePickerActivity; import com.nononsenseapps.notepad.util.AsyncTaskHelper; import com.nononsenseapps.notepad.util.PermissionsHelper; import com.nononsenseapps.notepad.util.PreferenceHelper; import com.nononsenseapps.notepad.util.SharedPreferencesHelper; import com.nononsenseapps.notepad.util.SyncGtaskHelper; import java.io.File; import java.util.ArrayList; import java.util.Locale; import static com.nononsenseapps.notepad.util.PermissionsHelper.hasPermissions; import static com.nononsenseapps.notepad.util.PermissionsHelper.permissionsGranted; import static com.nononsenseapps.notepad.util.SharedPreferencesHelper.disableDropboxSync; import static com.nononsenseapps.notepad.util.SharedPreferencesHelper.disableSdCardSync; import static com.nononsenseapps.notepad.util.SharedPreferencesHelper.getDropboxDir; import static com.nononsenseapps.notepad.util.SharedPreferencesHelper.getSdDir; /** * Main top level settings fragment */ public class FragmentSettings extends PreferenceFragment implements SharedPreferences .OnSharedPreferenceChangeListener { private static final int ACTIVITY_CODE_PICK_SD_DIR = 1; private static final int ACTIVITY_CODE_PICK_DROPBOX_DIR = 2; private static final int PERMISSION_CODE_GTASKS = 1; private static final int PERMISSION_CODE_SDCARD = 2; private SwitchPreference preferenceSyncSdCard; private SwitchPreference preferenceSyncGTasks; private SwitchPreference preferenceSyncDropbox; private DropboxSyncHelper mDropboxHelper = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the preferences from an XML resource addPreferencesFromResource(R.xml.settings); setLangEntries((ListPreference) findPreference(getString(R.string .const_preference_locale_key))); final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences (getActivity()); sharedPreferences.registerOnSharedPreferenceChangeListener(this); buildGuard(); setupAccount(sharedPreferences); setupDirectory(sharedPreferences); setupDropbox(sharedPreferences); setupPassword(); // Bind listeners to update summaries bindPreferenceSummaryToValue(R.string.const_preference_locale_key); bindPreferenceSummaryToValue(R.string.const_preference_theme_key); bindPreferenceSummaryToValue(R.string.const_preference_ringtone_key); } @Override public void onDestroy() { super.onDestroy(); PreferenceManager.getDefaultSharedPreferences(getActivity()) .unregisterOnSharedPreferenceChangeListener(this); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case ACTIVITY_CODE_PICK_SD_DIR: if (resultCode == Activity.RESULT_OK) { saveNewDirectoryPath(data); } else { disableSdCardSync(getActivity()); } break; case ACTIVITY_CODE_PICK_DROPBOX_DIR: if (resultCode == Activity.RESULT_OK) { saveNewDropboxPath(data); } else { disableDropboxSync(getActivity()); } break; default: super.onActivityResult(requestCode, resultCode, data); } } private void buildGuard() { // Disable prefs if this is not correct build findPreference(getString(R.string.const_preference_gtask_enabled_key)).setEnabled(null != Config.getGtasksApiKey(getActivity()) && !Config.getGtasksApiKey(getActivity()) .contains(" ")); } private void setupDirectory(final SharedPreferences sharedPreferences) { preferenceSyncSdCard = (SwitchPreference) findPreference(getString(R.string .const_preference_sdcard_enabled_key)); setSdDirectorySummary(sharedPreferences); } private void setupDropbox(final SharedPreferences sharedPreferences) { preferenceSyncDropbox = (SwitchPreference) findPreference(getString(R.string .const_preference_dropbox_enabled_key)); setDropboxDirectorySummary(sharedPreferences); preferenceSyncDropbox.setEnabled((BuildConfig.DROPBOX_ENABLED && Config.getKeyDropboxAPI (getActivity()) != null && !Config.getKeyDropboxAPISecret(getActivity()).contains(" "))); } private void showFilePicker() { if (hasSDCardPermissions()) { // Start the filepicker Intent i = new Intent(getActivity(), FilePickerActivity.class); i.putExtra(FilePickerActivity.EXTRA_START_PATH, getSdDir(getActivity())).putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false).putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true).putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR); startActivityForResult(i, ACTIVITY_CODE_PICK_SD_DIR); } else { requestSDCardPermissions(); } } private void showDropboxFilePicker() { if (mDropboxHelper == null) { mDropboxHelper = new DropboxSyncHelper(getActivity()); } if (mDropboxHelper.isLinked()) { saveDropboxAccountInBackground(); // Start the filepicker Intent i = new Intent(getActivity(), DropboxFilePickerActivity.class); i.putExtra(FilePickerActivity.EXTRA_START_PATH, getDropboxDir(getActivity())) .putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false).putExtra (FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true).putExtra(FilePickerActivity .EXTRA_MODE, FilePickerActivity.MODE_DIR); startActivityForResult(i, ACTIVITY_CODE_PICK_DROPBOX_DIR); } else { mDropboxHelper.linkAccount(); // See onResume for result } } private void setSdDirectorySummary(final SharedPreferences sharedPreferences) { preferenceSyncSdCard.setSummary(sharedPreferences.getString(getSdDirectoryKey(), SDSynchronizer.DEFAULT_ORG_DIR)); } private void setDropboxDirectorySummary(final SharedPreferences sharedPreferences) { preferenceSyncDropbox.setSummary(sharedPreferences.getString(getDropboxDirectoryKey(), DropboxSynchronizer.DEFAULT_DIR)); } @SuppressLint("CommitPrefEdits") private void saveNewDirectoryPath(Intent data) { File path = new File(data.getData().getPath()); if (path.exists() && path.isDirectory() && path.canWrite()) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences (getActivity()); sharedPreferences.edit().putString(getSdDirectoryKey(), path.toString()).commit(); setSdDirectorySummary(sharedPreferences); } else { Toast.makeText(getActivity(), R.string.cannot_write_to_directory, Toast.LENGTH_SHORT) .show(); disableSdCardSync(getActivity()); } } @SuppressLint("CommitPrefEdits") private void saveNewDropboxPath(Intent data) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences (getActivity()); sharedPreferences.edit().putString(getDropboxDirectoryKey(), data.getData().getPath()) .commit(); setDropboxDirectorySummary(sharedPreferences); } private String getSdDirectoryKey() { return getString(R.string.const_preference_sdcard_dir_key); } private String getDropboxDirectoryKey() { return getString(R.string.const_preference_dropbox_dir_key); } private void setupAccount(SharedPreferences sharedPreferences) { preferenceSyncGTasks = (SwitchPreference) findPreference(getString(R.string .const_preference_gtask_enabled_key)); setAccountSummary(sharedPreferences); } private void showAccountDialog() { if (hasGoogleAccountPermissions()) { FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("accountdialog"); if (prev != null) { ft.remove(prev); } ft.addToBackStack(null); // Create and show the dialog. DialogFragment newFragment = new DialogGoogleAccount(); newFragment.setArguments(Bundle.EMPTY); newFragment.show(ft, "accountdialog"); } else { requestGoogleAccountPermissions(); } } @TargetApi(Build.VERSION_CODES.M) private void requestGoogleAccountPermissions() { requestPermissions(PermissionsHelper.PERMISSIONS_GTASKS, PERMISSION_CODE_GTASKS); } @TargetApi(Build.VERSION_CODES.M) private void requestSDCardPermissions() { requestPermissions(PermissionsHelper.PERMISSIONS_SD, PERMISSION_CODE_SDCARD); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case PERMISSION_CODE_GTASKS: if (permissionsGranted(permissions, grantResults)) { // Success, open dialog showAccountDialog(); } else { Toast.makeText(getActivity(), "Permission denied :(. Show explanation for contacts", Toast.LENGTH_LONG).show(); SharedPreferencesHelper.put(getActivity(), R.string.const_preference_gtask_enabled_key, false); } break; case PERMISSION_CODE_SDCARD: if (permissionsGranted(permissions, grantResults)) { // Success, open picker showFilePicker(); } else { Toast.makeText(getActivity(), "Permission denied :(. Show explanation for SD card", Toast.LENGTH_LONG).show(); disableSdCardSync(getActivity()); } break; } } @Override public void onResume() { super.onResume(); if (mDropboxHelper != null && !mDropboxHelper.isLinked()) { if (mDropboxHelper.handleLinkResult()) { // Success, show file picker showDropboxFilePicker(); } else { // Link failed or was cancelled by the user. SharedPreferencesHelper.disableDropboxSync(getActivity()); } } } private void saveDropboxAccountInBackground() { // Save account name. Needs to be done in background AsyncTaskHelper.background(new AsyncTaskHelper.Job() { @Override public void doInBackground() { SharedPreferencesHelper.setDropboxAccount(getActivity(), mDropboxHelper.getAccount()); } }); } private boolean hasGoogleAccountPermissions() { return hasPermissions(getActivity(), PermissionsHelper.PERMISSIONS_GTASKS); } private boolean hasSDCardPermissions() { return hasPermissions(getActivity(), PermissionsHelper.PERMISSIONS_SD); } private void setupPassword() { Preference preference = findPreference(getString(R.string.const_preference_password_key)); if (preference != null) { preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { DialogPasswordSettings.showDialog(((AppCompatActivity) getActivity()) .getSupportFragmentManager()); return true; } }); } } private void bindPreferenceSummaryToValue(@StringRes int key) { Preference preference = findPreference(getString(key)); if (preference != null) { // Set change listener preference.setOnPreferenceChangeListener(PreferenceHelper.sSummaryUpdater); // Trigger the listener immediately with the preference's current value. PreferenceHelper.sSummaryUpdater.onPreferenceChange(preference, PreferenceManager .getDefaultSharedPreferences(preference.getContext()).getString(preference .getKey(), "")); } } private void setLangEntries(ListPreference prefLang) { ArrayList<CharSequence> entries = new ArrayList<>(); ArrayList<CharSequence> values = new ArrayList<>(); entries.add(getString(R.string.localedefault)); values.add(""); String[] langs = getResources().getStringArray(R.array.translated_langs); for (String lang : langs) { Locale l; if (lang.length() == 5) { l = new Locale(lang.substring(0, 2), lang.substring(3, 5)); } else { l = new Locale(lang.substring(0, 2)); } entries.add(l.getDisplayName(l)); values.add(lang); } prefLang.setEntries(entries.toArray(new CharSequence[entries.size()])); prefLang.setEntryValues(values.toArray(new CharSequence[values.size()])); // Set summary prefLang.setSummary(prefLang.getEntry()); } /** * Called when a shared preference is changed, added, or removed. This * may be called even if a preference is set to its existing value. * <p/> * <p>This callback will be run on your main thread. * * @param sharedPreferences The {@link SharedPreferences} that received * the change. * @param key The key of the preference that was changed, added, or */ @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { try { if (getActivity().isFinishing()) { return; } if (key.equals(getString(R.string.const_preference_gtask_enabled_key))) { final boolean enabled = sharedPreferences.getBoolean(getString(R.string .const_preference_gtask_enabled_key), false); if (enabled) { showAccountDialog(); } else { SyncGtaskHelper.toggleSync(getActivity(), sharedPreferences); // Synchronize view also if (preferenceSyncGTasks.isChecked()) { preferenceSyncGTasks.setChecked(false); } } } else if (key.equals(getString(R.string.const_preference_gtask_account_key))) { setAccountSummary(sharedPreferences); } else if (key.equals(getString(R.string.const_preference_sdcard_enabled_key))) { final boolean enabled = sharedPreferences.getBoolean(getString(R.string .const_preference_sdcard_enabled_key), false); if (enabled) { showFilePicker(); } else { // Restart the service (started in activities) OrgSyncService.stop(getActivity()); // Synchronize view also if (preferenceSyncSdCard.isChecked()) { preferenceSyncSdCard.setChecked(false); } } } else if (key.equals(getString(R.string.const_preference_dropbox_enabled_key))) { if (!(BuildConfig.DROPBOX_ENABLED && Config.getKeyDropboxAPI(getActivity()) != null && !Config.getKeyDropboxAPISecret(getActivity()).contains(" "))) { return; } final boolean enabled = sharedPreferences.getBoolean(getString(R.string .const_preference_dropbox_enabled_key), false); if (enabled) { showDropboxFilePicker(); } else { SharedPreferencesHelper.disableDropboxSync(getActivity()); // Restart the service (started in activities) OrgSyncService.stop(getActivity()); // Synchronize view also if (preferenceSyncDropbox.isChecked()) { preferenceSyncDropbox.setChecked(false); } } } } catch (IllegalStateException ignored) { // In case isFinishing isn't guard enough } } private void setAccountSummary(SharedPreferences sharedPreferences) { preferenceSyncGTasks.setSummary(sharedPreferences.getString(getString(R.string .const_preference_gtask_account_key), getString(R.string .settings_account_summary))); } }