package info.knacki.pass.settings.ui; import android.annotation.TargetApi; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.preference.SwitchPreference; import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBar; import android.util.SparseArray; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import java.io.File; import java.util.List; import java.util.logging.Logger; import info.knacki.pass.R; import info.knacki.pass.git.GitInterface; import info.knacki.pass.git.GitInterfaceFactory; import info.knacki.pass.git.entities.GitRef; import info.knacki.pass.io.FileUtils; import info.knacki.pass.io.PathUtils; import info.knacki.pass.settings.SettingsManager; import info.knacki.pass.ui.GitPullActivity; import info.knacki.pass.ui.alertPrompt.AlertPrompt; import info.knacki.pass.ui.alertPrompt.views.TextView; /** * A {@link PreferenceActivity} that presents a set of application settings. On * handset devices, settings are presented as a single list. On tablets, * settings are split by category, with category headers shown to the left of * the list of settings. *

* See * Android Design: Settings for design guidelines and the Settings * API Guide for more information on developing a Settings UI. */ public class SettingsActivity extends AppCompatPreferenceActivity { private static final Logger log = Logger.getLogger(SettingsActivity.class.getName()); /** * Helper method to determine if the device has an extra-large screen. For * example, 10" tablets are extra-large. */ private static boolean isXLargeTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setupActionBar(); } /** * Set up the {@link android.app.ActionBar}, if the API is available. */ private void setupActionBar() { ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { // Show the Up button in the action bar. actionBar.setDisplayHomeAsUpEnabled(true); } } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { if (!super.onMenuItemSelected(featureId, item)) { NavUtils.navigateUpFromSameTask(this); } return true; } return super.onMenuItemSelected(featureId, item); } /** * {@inheritDoc} */ @Override public boolean onIsMultiPane() { return isXLargeTablet(this); } /** * {@inheritDoc} */ @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void onBuildHeaders(List

target) { loadHeadersFromResource(R.xml.pref_headers, target); } /** * This method stops fragment injection in malicious applications. * Make sure to deny any unknown fragments here. */ protected boolean isValidFragment(String fragmentName) { return PreferenceFragment.class.getName().equals(fragmentName) || GeneralPreferenceFragment.class.getName().equals(fragmentName) || EncryptionPreferenceFragment.class.getName().equals(fragmentName) || VCSPreferenceFragment.class.getName().equals(fragmentName) || GPGPreferenceFragment.class.getName().equals(fragmentName); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class GeneralPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_general); setHasOptionsMenu(true); findPreference(getResources().getString(R.string.id_softSettings)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { //FIXME return true; } }); findPreference(getResources().getString(R.string.id_removeall)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { new AlertPrompt(getActivity()) .setTitle(R.string.are_you_sure) .setView(new TextView(getActivity()) .SetText(R.string.about_to_rm_root_star)) .setPositiveButton(R.string.ok, new AlertPrompt.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, View view) { new File(PathUtils.GetGitFile(getActivity())).delete(); File f = new File(PathUtils.GetPassDir(getActivity())); FileUtils.rmdir(f); f.mkdir(); } }) .setNegativeButton(R.string.cancel, new AlertPrompt.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, View view) { } }) .show(); return true; } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { startActivity(new Intent(getActivity(), SettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class EncryptionPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_encryption); setHasOptionsMenu(true); ListPreference encTypePref = (ListPreference) findPreference(getResources().getString(R.string.id_enctype)); final int encTypeIndex = SettingsManager.GetDefaultEncryptionType(getActivity()).IntValue(); encTypePref.setSummary(encTypePref.getEntries()[encTypeIndex]); encTypePref.setValueIndex(encTypeIndex); encTypePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object o) { int value = Integer.parseInt(o.toString()); preference.setSummary(((ListPreference) preference).getEntries()[value]); SettingsManager.SetDefaultEncryptionType(getActivity(), SettingsManager.EncryptionType.FromInt(value)); return true; } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { startActivity(new Intent(getActivity(), SettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class VCSPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_vcs); setHasOptionsMenu(true); abstract class PrefListener implements Preference.OnPreferenceChangeListener { @Override public boolean onPreferenceChange(Preference preference, Object o) { savePref(preference, o); VCSPreferenceFragment.this.reload(); return true; } abstract void savePref(Preference preference, Object o); } findPreference(getResources().getString(R.string.id_vcs_enable)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { if ((Boolean) o) SettingsManager.SetVCS(getActivity(), new SettingsManager.Git()); else SettingsManager.SetVCS(getActivity(), null); } }); findPreference(getResources().getString(R.string.id_vcs_list)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.VCS vcs = SettingsManager.GetVCS(getActivity()); SettingsManager.VCS newVcs; switch (Integer.parseInt((String) o)) { case 0: newVcs = new SettingsManager.Git(); break; default: return; } if (!vcs.GetName().equals(newVcs.GetName())) { SettingsManager.SetVCS(getActivity(), newVcs); } } }); findPreference(getResources().getString(R.string.id_vcs_git_url)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetUrl(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_user)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetUser(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_pass)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetPassword(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_ci_username)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetUsername(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_ci_useremail)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetUserEmail(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_branches)).setOnPreferenceChangeListener(new PrefListener() { @Override void savePref(Preference preference, Object o) { SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity()); git.SetBranch(((String) o).trim()); SettingsManager.SetVCS(getActivity(), git); } }); findPreference(getResources().getString(R.string.id_vcs_git_pull)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { startActivity(new Intent(getActivity(), GitPullActivity.class)); return true; } }); reload(); } final SparseArray hiddenPreferences = new SparseArray<>(); private void RemovePrefs(int... prefIds) { for (int id: prefIds) { Preference pref = findPreference(getResources().getString(id)); if (pref != null) { getPreferenceScreen().removePreference(pref); hiddenPreferences.put(id, pref); } } } private Preference FindPreference(int prefId) { Preference p = findPreference(getResources().getString(prefId)); if (p != null) return p; p = hiddenPreferences.get(prefId); hiddenPreferences.remove(prefId); if (p != null) getPreferenceScreen().addPreference(p); return p; } protected void reload() { final SettingsManager.VCS versioning = SettingsManager.GetVCS(getActivity()); if (versioning != null) { ((SwitchPreference) findPreference(getResources().getString(R.string.id_vcs_enable))).setChecked(true); ListPreference vcsType = (ListPreference) FindPreference(R.string.id_vcs_list); vcsType.setEnabled(true); if (versioning instanceof SettingsManager.Git) { vcsType.setValueIndex(0); vcsType.setSummary(vcsType.getEntries()[0]); EditTextPreference gitUrl = (EditTextPreference) FindPreference(R.string.id_vcs_git_url); gitUrl.setSummary(((SettingsManager.Git) versioning).GetUrl()); gitUrl.setText(((SettingsManager.Git) versioning).GetUrl()); FindPreference(R.string.id_vcs_git_authcategory); EditTextPreference gitUser = (EditTextPreference) FindPreference(R.string.id_vcs_git_user); gitUser.setSummary(((SettingsManager.Git) versioning).GetUser()); gitUser.setText(((SettingsManager.Git) versioning).GetUser()); EditTextPreference gitPass = (EditTextPreference) FindPreference(R.string.id_vcs_git_pass); gitPass.setSummary(((SettingsManager.Git) versioning).GetPassword().length() == 0 ? "" : "******"); gitPass.setText(((SettingsManager.Git) versioning).GetPassword()); FindPreference(R.string.id_vcs_git_commitinfocategory); ListPreference gitBranches = (ListPreference) FindPreference(R.string.id_vcs_git_branches); populateBranches(gitBranches, (SettingsManager.Git) versioning); FindPreference(R.string.id_vcs_git_pull); EditTextPreference gitUsername = (EditTextPreference) FindPreference(R.string.id_vcs_git_ci_username); gitUsername.setSummary(((SettingsManager.Git) versioning).GetUsername()); gitUsername.setDefaultValue(((SettingsManager.Git) versioning).GetUsername()); EditTextPreference gitUserEmail = (EditTextPreference) FindPreference(R.string.id_vcs_git_ci_useremail); gitUserEmail.setSummary(((SettingsManager.Git) versioning).GetUserEmail()); gitUserEmail.setDefaultValue(((SettingsManager.Git) versioning).GetUserEmail()); } else { RemovePrefs(R.string.id_vcs_git_url, R.string.id_vcs_git_user, R.string.id_vcs_git_pass, R.string.id_vcs_git_branches, R.string.id_vcs_git_pull, R.string.id_vcs_git_ci_username, R.string.id_vcs_git_ci_useremail, R.string.id_vcs_git_commitinfocategory, R.string.id_vcs_git_authcategory); } } else { ((SwitchPreference) findPreference(getResources().getString(R.string.id_vcs_enable))).setChecked(false); ListPreference vcsType = (ListPreference) findPreference(getResources().getString(R.string.id_vcs_list)); vcsType.setEnabled(false); vcsType.setSummary(""); RemovePrefs(R.string.id_vcs_git_url, R.string.id_vcs_git_user, R.string.id_vcs_git_pass, R.string.id_vcs_git_branches, R.string.id_vcs_git_pull, R.string.id_vcs_git_ci_username, R.string.id_vcs_git_ci_useremail, R.string.id_vcs_git_commitinfocategory, R.string.id_vcs_git_authcategory); } } protected void populateBranches(final ListPreference gitBranches, final SettingsManager.Git versioning) { gitBranches.setEnabled(false); GitInterface gitInterface = GitInterfaceFactory.factory(getActivity(), versioning); if (gitInterface != null) { gitInterface.GetRefs(new GitInterface.OnResponseListener() { @Override public void onResponse(final GitRef[] result) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { CharSequence[] refNames = new CharSequence[result.length]; CharSequence[] refs = new CharSequence[result.length]; int selected = -1; for (int i = 0; i < result.length; ++i) { refNames[i] = result[i].GetBranchName(); refs[i] = result[i].GetBranch(); if (result[i].GetBranch().equals(versioning.GetBranch())) selected = i; } gitBranches.setEntries(refNames); gitBranches.setEntryValues(refs); gitBranches.setEnabled(true); if (selected >= 0) { gitBranches.setSummary(refNames[selected]); gitBranches.setValueIndex(selected); } } }); } @Override public void onError(final String msg, final Throwable e) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show(); } }); } }); } else { gitBranches.setEntryValues(new CharSequence[]{}); gitBranches.setEntries(new CharSequence[]{}); gitBranches.setEnabled(false); } } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == android.R.id.home) { startActivity(new Intent(getActivity(), SettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } public final static int ACTIVITY_REQUEST_CODE_BROWSEGPG = 1; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class GPGPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_gpg); setHasOptionsMenu(true); findPreference(getResources().getString(R.string.id_gpg_keyfile)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.setType("file/*"); GPGPreferenceFragment.this.startActivityForResult(i, ACTIVITY_REQUEST_CODE_BROWSEGPG); return true; } }); updateGpgFileLabel(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == ACTIVITY_REQUEST_CODE_BROWSEGPG) { if (resultCode == RESULT_OK) { Uri uriData = data.getData(); if (null != uriData) { String path = uriData.getPath(); SettingsManager.SetGPGKeyFile(getActivity(), path); updateGpgFileLabel(); } } } } protected void updateGpgFileLabel() { String gpgFileName = SettingsManager.GetGPGKeyFile(getActivity()); File gpgFile = gpgFileName == null ? null : new File(gpgFileName); if (gpgFile != null && gpgFile.exists()) { findPreference(getResources().getString(R.string.id_gpg_keyfile)).setSummary(gpgFile.getName()); } else { findPreference(getResources().getString(R.string.id_gpg_keyfile)).setSummary(R.string.pref_summary_gpg_keyfile); } } } }