SettingsActivity.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package info.knacki.pass.settings.ui;
  2. import android.annotation.TargetApi;
  3. import android.content.Context;
  4. import android.content.DialogInterface;
  5. import android.content.Intent;
  6. import android.content.res.Configuration;
  7. import android.net.Uri;
  8. import android.os.Build;
  9. import android.os.Bundle;
  10. import android.preference.EditTextPreference;
  11. import android.preference.ListPreference;
  12. import android.preference.Preference;
  13. import android.preference.PreferenceActivity;
  14. import android.preference.PreferenceFragment;
  15. import android.preference.SwitchPreference;
  16. import android.support.v4.app.NavUtils;
  17. import android.support.v7.app.ActionBar;
  18. import android.util.SparseArray;
  19. import android.view.MenuItem;
  20. import android.view.View;
  21. import android.widget.Toast;
  22. import java.io.File;
  23. import java.util.List;
  24. import java.util.logging.Logger;
  25. import info.knacki.pass.R;
  26. import info.knacki.pass.git.GitInterface;
  27. import info.knacki.pass.git.GitInterfaceFactory;
  28. import info.knacki.pass.git.entities.GitRef;
  29. import info.knacki.pass.io.FileUtils;
  30. import info.knacki.pass.io.PathUtils;
  31. import info.knacki.pass.settings.SettingsManager;
  32. import info.knacki.pass.ui.GitPullActivity;
  33. import info.knacki.pass.ui.alertPrompt.AlertPrompt;
  34. import info.knacki.pass.ui.alertPrompt.views.TextView;
  35. /**
  36. * A {@link PreferenceActivity} that presents a set of application settings. On
  37. * handset devices, settings are presented as a single list. On tablets,
  38. * settings are split by category, with category headers shown to the left of
  39. * the list of settings.
  40. * <p>
  41. * See <a href="http://developer.android.com/design/patterns/settings.html">
  42. * Android Design: Settings</a> for design guidelines and the <a
  43. * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
  44. * API Guide</a> for more information on developing a Settings UI.
  45. */
  46. public class SettingsActivity extends AppCompatPreferenceActivity {
  47. private static final Logger log = Logger.getLogger(SettingsActivity.class.getName());
  48. /**
  49. * Helper method to determine if the device has an extra-large screen. For
  50. * example, 10" tablets are extra-large.
  51. */
  52. private static boolean isXLargeTablet(Context context) {
  53. return (context.getResources().getConfiguration().screenLayout
  54. & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
  55. }
  56. @Override
  57. protected void onCreate(Bundle savedInstanceState) {
  58. super.onCreate(savedInstanceState);
  59. setupActionBar();
  60. }
  61. /**
  62. * Set up the {@link android.app.ActionBar}, if the API is available.
  63. */
  64. private void setupActionBar() {
  65. ActionBar actionBar = getSupportActionBar();
  66. if (actionBar != null) {
  67. // Show the Up button in the action bar.
  68. actionBar.setDisplayHomeAsUpEnabled(true);
  69. }
  70. }
  71. @Override
  72. public boolean onMenuItemSelected(int featureId, MenuItem item) {
  73. int id = item.getItemId();
  74. if (id == android.R.id.home) {
  75. if (!super.onMenuItemSelected(featureId, item)) {
  76. NavUtils.navigateUpFromSameTask(this);
  77. }
  78. return true;
  79. }
  80. return super.onMenuItemSelected(featureId, item);
  81. }
  82. /**
  83. * {@inheritDoc}
  84. */
  85. @Override
  86. public boolean onIsMultiPane() {
  87. return isXLargeTablet(this);
  88. }
  89. /**
  90. * {@inheritDoc}
  91. */
  92. @Override
  93. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  94. public void onBuildHeaders(List<Header> target) {
  95. loadHeadersFromResource(R.xml.pref_headers, target);
  96. }
  97. /**
  98. * This method stops fragment injection in malicious applications.
  99. * Make sure to deny any unknown fragments here.
  100. */
  101. protected boolean isValidFragment(String fragmentName) {
  102. return PreferenceFragment.class.getName().equals(fragmentName)
  103. || GeneralPreferenceFragment.class.getName().equals(fragmentName)
  104. || EncryptionPreferenceFragment.class.getName().equals(fragmentName)
  105. || VCSPreferenceFragment.class.getName().equals(fragmentName)
  106. || GPGPreferenceFragment.class.getName().equals(fragmentName);
  107. }
  108. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  109. public static class GeneralPreferenceFragment extends PreferenceFragment {
  110. @Override
  111. public void onCreate(Bundle savedInstanceState) {
  112. super.onCreate(savedInstanceState);
  113. addPreferencesFromResource(R.xml.pref_general);
  114. setHasOptionsMenu(true);
  115. findPreference(getResources().getString(R.string.id_softSettings)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  116. @Override
  117. public boolean onPreferenceClick(Preference preference) {
  118. //FIXME
  119. return true;
  120. }
  121. });
  122. findPreference(getResources().getString(R.string.id_removeall)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  123. @Override
  124. public boolean onPreferenceClick(Preference preference) {
  125. new AlertPrompt(getActivity())
  126. .setTitle(R.string.are_you_sure)
  127. .setView(new TextView(getActivity())
  128. .SetText(R.string.about_to_rm_root_star))
  129. .setPositiveButton(R.string.ok, new AlertPrompt.OnClickListener() {
  130. @Override
  131. public void onClick(DialogInterface dialogInterface, View view) {
  132. new File(PathUtils.GetGitFile(getActivity())).delete();
  133. File f = new File(PathUtils.GetPassDir(getActivity()));
  134. FileUtils.rmdir(f);
  135. f.mkdir();
  136. }
  137. })
  138. .setNegativeButton(R.string.cancel, new AlertPrompt.OnClickListener() {
  139. @Override
  140. public void onClick(DialogInterface dialogInterface, View view) {
  141. }
  142. })
  143. .show();
  144. return true;
  145. }
  146. });
  147. }
  148. @Override
  149. public boolean onOptionsItemSelected(MenuItem item) {
  150. int id = item.getItemId();
  151. if (id == android.R.id.home) {
  152. startActivity(new Intent(getActivity(), SettingsActivity.class));
  153. return true;
  154. }
  155. return super.onOptionsItemSelected(item);
  156. }
  157. }
  158. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  159. public static class EncryptionPreferenceFragment extends PreferenceFragment {
  160. @Override
  161. public void onCreate(Bundle savedInstanceState) {
  162. super.onCreate(savedInstanceState);
  163. addPreferencesFromResource(R.xml.pref_encryption);
  164. setHasOptionsMenu(true);
  165. ListPreference encTypePref = (ListPreference) findPreference(getResources().getString(R.string.id_enctype));
  166. final int encTypeIndex = SettingsManager.GetDefaultEncryptionType(getActivity()).IntValue();
  167. encTypePref.setSummary(encTypePref.getEntries()[encTypeIndex]);
  168. encTypePref.setValueIndex(encTypeIndex);
  169. encTypePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
  170. @Override
  171. public boolean onPreferenceChange(Preference preference, Object o) {
  172. int value = Integer.parseInt(o.toString());
  173. preference.setSummary(((ListPreference) preference).getEntries()[value]);
  174. SettingsManager.SetDefaultEncryptionType(getActivity(), SettingsManager.EncryptionType.FromInt(value));
  175. return true;
  176. }
  177. });
  178. }
  179. @Override
  180. public boolean onOptionsItemSelected(MenuItem item) {
  181. int id = item.getItemId();
  182. if (id == android.R.id.home) {
  183. startActivity(new Intent(getActivity(), SettingsActivity.class));
  184. return true;
  185. }
  186. return super.onOptionsItemSelected(item);
  187. }
  188. }
  189. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  190. public static class VCSPreferenceFragment extends PreferenceFragment {
  191. @Override
  192. public void onCreate(Bundle savedInstanceState) {
  193. super.onCreate(savedInstanceState);
  194. addPreferencesFromResource(R.xml.pref_vcs);
  195. setHasOptionsMenu(true);
  196. abstract class PrefListener implements Preference.OnPreferenceChangeListener {
  197. @Override
  198. public boolean onPreferenceChange(Preference preference, Object o) {
  199. savePref(preference, o);
  200. VCSPreferenceFragment.this.reload();
  201. return true;
  202. }
  203. abstract void savePref(Preference preference, Object o);
  204. }
  205. findPreference(getResources().getString(R.string.id_vcs_enable)).setOnPreferenceChangeListener(new PrefListener() {
  206. @Override
  207. void savePref(Preference preference, Object o) {
  208. if ((Boolean) o)
  209. SettingsManager.SetVCS(getActivity(), new SettingsManager.Git());
  210. else
  211. SettingsManager.SetVCS(getActivity(), null);
  212. }
  213. });
  214. findPreference(getResources().getString(R.string.id_vcs_list)).setOnPreferenceChangeListener(new PrefListener() {
  215. @Override
  216. void savePref(Preference preference, Object o) {
  217. SettingsManager.VCS vcs = SettingsManager.GetVCS(getActivity());
  218. SettingsManager.VCS newVcs;
  219. switch (Integer.parseInt((String) o)) {
  220. case 0:
  221. newVcs = new SettingsManager.Git();
  222. break;
  223. default:
  224. return;
  225. }
  226. if (!vcs.GetName().equals(newVcs.GetName())) {
  227. SettingsManager.SetVCS(getActivity(), newVcs);
  228. }
  229. }
  230. });
  231. findPreference(getResources().getString(R.string.id_vcs_git_url)).setOnPreferenceChangeListener(new PrefListener() {
  232. @Override
  233. void savePref(Preference preference, Object o) {
  234. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  235. git.SetUrl(((String) o).trim());
  236. SettingsManager.SetVCS(getActivity(), git);
  237. }
  238. });
  239. findPreference(getResources().getString(R.string.id_vcs_git_user)).setOnPreferenceChangeListener(new PrefListener() {
  240. @Override
  241. void savePref(Preference preference, Object o) {
  242. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  243. git.SetUser(((String) o).trim());
  244. SettingsManager.SetVCS(getActivity(), git);
  245. }
  246. });
  247. findPreference(getResources().getString(R.string.id_vcs_git_pass)).setOnPreferenceChangeListener(new PrefListener() {
  248. @Override
  249. void savePref(Preference preference, Object o) {
  250. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  251. git.SetPassword(((String) o).trim());
  252. SettingsManager.SetVCS(getActivity(), git);
  253. }
  254. });
  255. findPreference(getResources().getString(R.string.id_vcs_git_ci_username)).setOnPreferenceChangeListener(new PrefListener() {
  256. @Override
  257. void savePref(Preference preference, Object o) {
  258. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  259. git.SetUsername(((String) o).trim());
  260. SettingsManager.SetVCS(getActivity(), git);
  261. }
  262. });
  263. findPreference(getResources().getString(R.string.id_vcs_git_ci_useremail)).setOnPreferenceChangeListener(new PrefListener() {
  264. @Override
  265. void savePref(Preference preference, Object o) {
  266. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  267. git.SetUserEmail(((String) o).trim());
  268. SettingsManager.SetVCS(getActivity(), git);
  269. }
  270. });
  271. findPreference(getResources().getString(R.string.id_vcs_git_branches)).setOnPreferenceChangeListener(new PrefListener() {
  272. @Override
  273. void savePref(Preference preference, Object o) {
  274. SettingsManager.Git git = (SettingsManager.Git) SettingsManager.GetVCS(getActivity());
  275. git.SetBranch(((String) o).trim());
  276. SettingsManager.SetVCS(getActivity(), git);
  277. }
  278. });
  279. findPreference(getResources().getString(R.string.id_vcs_git_pull)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  280. @Override
  281. public boolean onPreferenceClick(Preference preference) {
  282. startActivity(new Intent(getActivity(), GitPullActivity.class));
  283. return true;
  284. }
  285. });
  286. reload();
  287. }
  288. final SparseArray<Preference> hiddenPreferences = new SparseArray<>();
  289. private void RemovePrefs(int... prefIds) {
  290. for (int id: prefIds) {
  291. Preference pref = findPreference(getResources().getString(id));
  292. if (pref != null) {
  293. getPreferenceScreen().removePreference(pref);
  294. hiddenPreferences.put(id, pref);
  295. }
  296. }
  297. }
  298. private Preference FindPreference(int prefId) {
  299. Preference p = findPreference(getResources().getString(prefId));
  300. if (p != null)
  301. return p;
  302. p = hiddenPreferences.get(prefId);
  303. hiddenPreferences.remove(prefId);
  304. if (p != null)
  305. getPreferenceScreen().addPreference(p);
  306. return p;
  307. }
  308. protected void reload() {
  309. final SettingsManager.VCS versioning = SettingsManager.GetVCS(getActivity());
  310. if (versioning != null) {
  311. ((SwitchPreference) findPreference(getResources().getString(R.string.id_vcs_enable))).setChecked(true);
  312. ListPreference vcsType = (ListPreference) FindPreference(R.string.id_vcs_list);
  313. vcsType.setEnabled(true);
  314. if (versioning instanceof SettingsManager.Git) {
  315. vcsType.setValueIndex(0);
  316. vcsType.setSummary(vcsType.getEntries()[0]);
  317. EditTextPreference gitUrl = (EditTextPreference) FindPreference(R.string.id_vcs_git_url);
  318. gitUrl.setSummary(((SettingsManager.Git) versioning).GetUrl());
  319. gitUrl.setText(((SettingsManager.Git) versioning).GetUrl());
  320. FindPreference(R.string.id_vcs_git_authcategory);
  321. EditTextPreference gitUser = (EditTextPreference) FindPreference(R.string.id_vcs_git_user);
  322. gitUser.setSummary(((SettingsManager.Git) versioning).GetUser());
  323. gitUser.setText(((SettingsManager.Git) versioning).GetUser());
  324. EditTextPreference gitPass = (EditTextPreference) FindPreference(R.string.id_vcs_git_pass);
  325. gitPass.setSummary(((SettingsManager.Git) versioning).GetPassword().length() == 0 ? "" : "******");
  326. gitPass.setText(((SettingsManager.Git) versioning).GetPassword());
  327. FindPreference(R.string.id_vcs_git_commitinfocategory);
  328. ListPreference gitBranches = (ListPreference) FindPreference(R.string.id_vcs_git_branches);
  329. populateBranches(gitBranches, (SettingsManager.Git) versioning);
  330. FindPreference(R.string.id_vcs_git_pull);
  331. EditTextPreference gitUsername = (EditTextPreference) FindPreference(R.string.id_vcs_git_ci_username);
  332. gitUsername.setSummary(((SettingsManager.Git) versioning).GetUsername());
  333. gitUsername.setDefaultValue(((SettingsManager.Git) versioning).GetUsername());
  334. EditTextPreference gitUserEmail = (EditTextPreference) FindPreference(R.string.id_vcs_git_ci_useremail);
  335. gitUserEmail.setSummary(((SettingsManager.Git) versioning).GetUserEmail());
  336. gitUserEmail.setDefaultValue(((SettingsManager.Git) versioning).GetUserEmail());
  337. } else {
  338. RemovePrefs(R.string.id_vcs_git_url,
  339. R.string.id_vcs_git_user,
  340. R.string.id_vcs_git_pass,
  341. R.string.id_vcs_git_branches,
  342. R.string.id_vcs_git_pull,
  343. R.string.id_vcs_git_ci_username,
  344. R.string.id_vcs_git_ci_useremail,
  345. R.string.id_vcs_git_commitinfocategory,
  346. R.string.id_vcs_git_authcategory);
  347. }
  348. } else {
  349. ((SwitchPreference) findPreference(getResources().getString(R.string.id_vcs_enable))).setChecked(false);
  350. ListPreference vcsType = (ListPreference) findPreference(getResources().getString(R.string.id_vcs_list));
  351. vcsType.setEnabled(false);
  352. vcsType.setSummary("");
  353. RemovePrefs(R.string.id_vcs_git_url,
  354. R.string.id_vcs_git_user,
  355. R.string.id_vcs_git_pass,
  356. R.string.id_vcs_git_branches,
  357. R.string.id_vcs_git_pull,
  358. R.string.id_vcs_git_ci_username,
  359. R.string.id_vcs_git_ci_useremail,
  360. R.string.id_vcs_git_commitinfocategory,
  361. R.string.id_vcs_git_authcategory);
  362. }
  363. }
  364. protected void populateBranches(final ListPreference gitBranches, final SettingsManager.Git versioning) {
  365. gitBranches.setEnabled(false);
  366. GitInterface gitInterface = GitInterfaceFactory.factory(getActivity(), versioning);
  367. if (gitInterface != null) {
  368. gitInterface.GetRefs(new GitInterface.OnResponseListener<GitRef[]>() {
  369. @Override
  370. public void onResponse(final GitRef[] result) {
  371. getActivity().runOnUiThread(new Runnable() {
  372. @Override
  373. public void run() {
  374. CharSequence[] refNames = new CharSequence[result.length];
  375. CharSequence[] refs = new CharSequence[result.length];
  376. int selected = -1;
  377. for (int i = 0; i < result.length; ++i) {
  378. refNames[i] = result[i].GetBranchName();
  379. refs[i] = result[i].GetBranch();
  380. if (result[i].GetBranch().equals(versioning.GetBranch()))
  381. selected = i;
  382. }
  383. gitBranches.setEntries(refNames);
  384. gitBranches.setEntryValues(refs);
  385. gitBranches.setEnabled(true);
  386. if (selected >= 0) {
  387. gitBranches.setSummary(refNames[selected]);
  388. gitBranches.setValueIndex(selected);
  389. }
  390. }
  391. });
  392. }
  393. @Override
  394. public void onError(final String msg, final Throwable e) {
  395. getActivity().runOnUiThread(new Runnable() {
  396. @Override
  397. public void run() {
  398. Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
  399. }
  400. });
  401. }
  402. });
  403. } else {
  404. gitBranches.setEntryValues(new CharSequence[]{});
  405. gitBranches.setEntries(new CharSequence[]{});
  406. gitBranches.setEnabled(false);
  407. }
  408. }
  409. @Override
  410. public boolean onOptionsItemSelected(MenuItem item) {
  411. int id = item.getItemId();
  412. if (id == android.R.id.home) {
  413. startActivity(new Intent(getActivity(), SettingsActivity.class));
  414. return true;
  415. }
  416. return super.onOptionsItemSelected(item);
  417. }
  418. }
  419. public final static int ACTIVITY_REQUEST_CODE_BROWSEGPG = 1;
  420. @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  421. public static class GPGPreferenceFragment extends PreferenceFragment {
  422. @Override
  423. public void onCreate(Bundle savedInstanceState) {
  424. super.onCreate(savedInstanceState);
  425. addPreferencesFromResource(R.xml.pref_gpg);
  426. setHasOptionsMenu(true);
  427. findPreference(getResources().getString(R.string.id_gpg_keyfile)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  428. @Override
  429. public boolean onPreferenceClick(Preference preference) {
  430. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  431. i.setType("file/*");
  432. GPGPreferenceFragment.this.startActivityForResult(i, ACTIVITY_REQUEST_CODE_BROWSEGPG);
  433. return true;
  434. }
  435. });
  436. updateGpgFileLabel();
  437. }
  438. @Override
  439. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  440. if (requestCode == ACTIVITY_REQUEST_CODE_BROWSEGPG) {
  441. if (resultCode == RESULT_OK) {
  442. Uri uriData = data.getData();
  443. if (null != uriData) {
  444. String path = uriData.getPath();
  445. SettingsManager.SetGPGKeyFile(getActivity(), path);
  446. updateGpgFileLabel();
  447. }
  448. }
  449. }
  450. }
  451. protected void updateGpgFileLabel() {
  452. String gpgFileName = SettingsManager.GetGPGKeyFile(getActivity());
  453. File gpgFile = gpgFileName == null ? null : new File(gpgFileName);
  454. if (gpgFile != null && gpgFile.exists()) {
  455. findPreference(getResources().getString(R.string.id_gpg_keyfile)).setSummary(gpgFile.getName());
  456. } else {
  457. findPreference(getResources().getString(R.string.id_gpg_keyfile)).setSummary(R.string.pref_summary_gpg_keyfile);
  458. }
  459. }
  460. }
  461. }