diff options
author | Daniel Albert <albert_daniel@t-online.de> | 2014-06-28 12:30:30 +0200 |
---|---|---|
committer | Daniel Albert <albert_daniel@t-online.de> | 2014-06-28 12:30:30 +0200 |
commit | 2da5bfabd37260d009047ea2f54314a1264c1c6c (patch) | |
tree | e8a69b542d5c12dbb45d23fb2fb5d875fbf30bbb /OpenKeychain/src/main/java/org/sufficientlysecure | |
parent | d19c97a714410493fa89166c83aac774b435c866 (diff) | |
parent | 3f3e1cdb05ee0e5ab9a5a4aed8ac3ef4ef581f24 (diff) | |
download | open-keychain-2da5bfabd37260d009047ea2f54314a1264c1c6c.tar.gz open-keychain-2da5bfabd37260d009047ea2f54314a1264c1c6c.tar.bz2 open-keychain-2da5bfabd37260d009047ea2f54314a1264c1c6c.zip |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure')
11 files changed, 855 insertions, 71 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index d8a7e8427..e639824ec 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -22,8 +22,10 @@ import android.accounts.AccountManager; import android.content.*; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.provider.ContactsContract; import android.util.Patterns; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; @@ -58,7 +60,27 @@ public class ContactHelper { ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?"; - public static List<String> getMailAccounts(Context context) { + public static List<String> getPossibleUserEmails(Context context) { + Set<String> accountMails = getAccountEmails(context); + accountMails.addAll(getMainProfileContactEmails(context)); + // now return the Set (without duplicates) as a List + return new ArrayList<String>(accountMails); + } + + public static List<String> getPossibleUserNames(Context context) { + Set<String> accountMails = getAccountEmails(context); + Set<String> names = getContactNamesFromEmails(context, accountMails); + names.addAll(getMainProfileContactName(context)); + return new ArrayList<String>(names); + } + + /** + * Get emails from AccountManager + * + * @param context + * @return + */ + private static Set<String> getAccountEmails(Context context) { final Account[] accounts = AccountManager.get(context).getAccounts(); final Set<String> emailSet = new HashSet<String>(); for (Account account : accounts) { @@ -66,7 +88,118 @@ public class ContactHelper { emailSet.add(account.name); } } - return new ArrayList<String>(emailSet); + return emailSet; + } + + /** + * Search for contact names based on a list of emails (to find out the names of the + * device owner based on the email addresses from AccountsManager) + * + * @param context + * @param emails + * @return + */ + private static Set<String> getContactNamesFromEmails(Context context, Set<String> emails) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + Set<String> names = new HashSet<String>(); + for (String email : emails) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.Contacts.DISPLAY_NAME}, + ContactsContract.CommonDataKinds.Email.ADDRESS + "=?", + new String[]{email}, null + ); + if (profileCursor == null) return null; + + Set<String> currNames = new HashSet<String>(); + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(1); + Log.d(Constants.TAG, "name" + name); + if (name != null) { + currNames.add(name); + } + } + profileCursor.close(); + names.addAll(currNames); + } + return names; + } else { + return new HashSet<String>(); + } + } + + /** + * Retrieves the emails of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static Set<String> getMainProfileContactEmails(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query( + Uri.withAppendedPath( + ContactsContract.Profile.CONTENT_URI, + ContactsContract.Contacts.Data.CONTENT_DIRECTORY), + new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.CommonDataKinds.Email.IS_PRIMARY}, + + // Selects only email addresses + ContactsContract.Contacts.Data.MIMETYPE + "=?", + new String[]{ + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, + }, + // Show primary rows first. Note that there won't be a primary email address if the + // user hasn't specified one. + ContactsContract.Contacts.Data.IS_PRIMARY + " DESC" + ); + if (profileCursor == null) return null; + + Set<String> emails = new HashSet<String>(); + while (profileCursor.moveToNext()) { + String email = profileCursor.getString(0); + if (email != null) { + emails.add(email); + } + } + profileCursor.close(); + return emails; + } else { + return new HashSet<String>(); + } + } + + /** + * Retrieves the name of the primary profile contact + * http://developer.android.com/reference/android/provider/ContactsContract.Profile.html + * + * @param context + * @return + */ + private static List<String> getMainProfileContactName(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + ContentResolver resolver = context.getContentResolver(); + Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI, + new String[]{ContactsContract.Profile.DISPLAY_NAME}, + null, null, null); + if (profileCursor == null) return null; + + Set<String> names = new HashSet<String>(); + // should only contain one entry! + while (profileCursor.moveToNext()) { + String name = profileCursor.getString(0); + if (name != null) { + names.add(name); + } + } + profileCursor.close(); + return new ArrayList<String>(names); + } else { + return new ArrayList<String>(); + } } public static List<String> getContactMails(Context context) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java index f2b5e68eb..b45e8a6bb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java @@ -20,19 +20,13 @@ package org.sufficientlysecure.keychain.ui; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; -import android.view.View; -import android.view.View.OnClickListener; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.remote.ui.AccountsListFragment; import org.sufficientlysecure.keychain.util.Log; public class EditKeyActivityNew extends ActionBarActivity { - private Uri mDataUri; - private EditKeyFragment mEditKeyFragment; @Override @@ -41,25 +35,6 @@ public class EditKeyActivityNew extends ActionBarActivity { setContentView(R.layout.edit_key_activity_new); -// // Inflate a "Done"/"Cancel" custom action bar view -// ActionBarHelper.setTwoButtonView(getSupportActionBar(), -// R.string.btn_save, R.drawable.ic_action_save, -// new OnClickListener() { -// @Override -// public void onClick(View v) { -// // Save -// -// } -// }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, -// new OnClickListener() { -// @Override -// public void onClick(View v) { -// // Cancel -// -// } -// } -// ); - Uri dataUri = getIntent().getData(); if (dataUri == null) { Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index ac4390eac..3f330ee94 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -27,6 +27,7 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.app.ActionBarActivity; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -45,6 +46,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsArrayAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; @@ -68,6 +70,7 @@ public class EditKeyFragment extends LoaderFragment implements private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mKeysAdapter; + private UserIdsArrayAdapter mUserIdsAddedAdapter; private Uri mDataUri; @@ -180,6 +183,10 @@ public class EditKeyFragment extends LoaderFragment implements } }); + mUserIdsAddedAdapter = new UserIdsArrayAdapter(getActivity()); + mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); + mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); + mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0); mKeysList.setAdapter(mKeysAdapter); @@ -321,9 +328,17 @@ public class EditKeyFragment extends LoaderFragment implements Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { - if (message.what == AddUserIdDialogFragment.MESSAGE_OK) { + switch (message.what) { + case AddUserIdDialogFragment.MESSAGE_OKAY: + Bundle data = message.getData(); + String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID); + if (userId != null) { + mSaveKeyringParcel.addUserIds.add(userId); + mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); + } } + getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); } }; @@ -345,5 +360,4 @@ public class EditKeyFragment extends LoaderFragment implements // TODO } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index f7455905d..60162a682 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; +import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.net.Uri; @@ -66,6 +67,8 @@ public class ImportKeysActivity extends ActionBarActivity { + "IMPORT_KEY_FROM_KEYSERVER"; public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN"; + public static final String ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN = Constants.INTENT_PREFIX + + "IMPORT_KEY_FROM_FILE_AND_RETURN"; public static final String ACTION_IMPORT_KEY_FROM_KEYBASE = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEYBASE"; @@ -224,7 +227,8 @@ public class ImportKeysActivity extends ActionBarActivity { ); return; } - } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { + } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action) + || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { // NOTE: this only displays the appropriate fragment, no actions are taken mSwitchToTab = TAB_FILE; @@ -509,12 +513,13 @@ public class ImportKeysActivity extends ActionBarActivity { } */ - /* if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) { - ImportKeysActivity.this.setResult(Activity.RESULT_OK, mPendingIntentData); - finish(); + ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); + ImportKeysActivity.this.finish(); + } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { + ImportKeysActivity.this.setResult(RESULT_OK); + ImportKeysActivity.this.finish(); } - */ } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 84fd513a0..160869895 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -207,7 +207,9 @@ public class ImportKeysListFragment extends ListFragment implements if (getLoaderManager().getLoader(LOADER_ID_KEYBASE) != null) { getLoaderManager().destroyLoader(LOADER_ID_KEYBASE); } - setListShown(true); + if (getView() != null) { + setListShown(true); + } } private void restartLoaders() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index de16142d6..7ce7a06aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -113,10 +113,10 @@ public class KeyListActivity extends DrawerActivity { } private void createKey() { - Intent intent = new Intent(this, EditKeyActivity.class); - intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); - intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); - intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view + Intent intent = new Intent(this, WizardActivity.class); +// intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); +// intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); +// intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view startActivityForResult(intent, 0); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java new file mode 100644 index 000000000..20b47ed01 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java @@ -0,0 +1,466 @@ +/* + * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * 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 org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBarActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RadioGroup; +import android.widget.TextView; + +import org.sufficientlysecure.htmltextview.HtmlTextView; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.regex.Matcher; + + +public class WizardActivity extends ActionBarActivity { + + private State mCurrentState; + + // values for mCurrentScreen + private enum State { + START, CREATE_KEY, IMPORT_KEY, K9 + } + + public static final int REQUEST_CODE_IMPORT = 0x00007703; + + Button mBackButton; + Button mNextButton; + StartFragment mStartFragment; + CreateKeyFragment mCreateKeyFragment; + K9Fragment mK9Fragment; + + private static final String K9_PACKAGE = "com.fsck.k9"; + // private static final String K9_MARKET_INTENT_URI_BASE = "market://details?id=%s"; +// private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse( +// String.format(K9_MARKET_INTENT_URI_BASE, K9_PACKAGE))); + private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/k9mail/k-9/releases/tag/4.904")); + + LinearLayout mProgressLayout; + View mProgressLine; + ProgressBar mProgressBar; + ImageView mProgressImage; + TextView mProgressText; + + /** + * Checks if text of given EditText is not empty. If it is empty an error is + * set and the EditText gets the focus. + * + * @param context + * @param editText + * @return true if EditText is not empty + */ + private static boolean isEditTextNotEmpty(Context context, EditText editText) { + boolean output = true; + if (editText.getText().toString().length() == 0) { + editText.setError("empty!"); + editText.requestFocus(); + output = false; + } else { + editText.setError(null); + } + + return output; + } + + public static class StartFragment extends Fragment { + public static StartFragment newInstance() { + StartFragment myFragment = new StartFragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.wizard_start_fragment, + container, false); + } + } + + public static class CreateKeyFragment extends Fragment { + public static CreateKeyFragment newInstance() { + CreateKeyFragment myFragment = new CreateKeyFragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.wizard_create_key_fragment, + container, false); + + final AutoCompleteTextView emailView = (AutoCompleteTextView) view.findViewById(R.id.email); + emailView.setThreshold(1); // Start working from first character + emailView.setAdapter( + new ArrayAdapter<String> + (getActivity(), android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserEmails(getActivity()) + ) + ); + emailView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void afterTextChanged(Editable editable) { + String email = editable.toString(); + if (email.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (emailMatcher.matches()) { + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_ok, 0); + } else { + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_bad, 0); + } + } else { + // remove drawable if email is empty + emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + }); + final AutoCompleteTextView nameView = (AutoCompleteTextView) view.findViewById(R.id.name); + nameView.setThreshold(1); // Start working from first character + nameView.setAdapter( + new ArrayAdapter<String> + (getActivity(), android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserNames(getActivity()) + ) + ); + return view; + } + } + + public static class K9Fragment extends Fragment { + public static K9Fragment newInstance() { + K9Fragment myFragment = new K9Fragment(); + + Bundle args = new Bundle(); + myFragment.setArguments(args); + + return myFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.wizard_k9_fragment, + container, false); + + HtmlTextView text = (HtmlTextView) v + .findViewById(R.id.wizard_k9_text); + text.setHtmlFromString("Install K9. It's good for you! Here is a screenhot how to enable OK in K9: (TODO)", true); + + return v; + } + + } + + /** + * Loads new fragment + * + * @param fragment + */ + private void loadFragment(Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager + .beginTransaction(); + fragmentTransaction.replace(R.id.wizard_container, + fragment); + fragmentTransaction.commit(); + } + + /** + * Instantiate View and initialize fragments for this Activity + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.wizard_activity); + mBackButton = (Button) findViewById(R.id.wizard_back); + mNextButton = (Button) findViewById(R.id.wizard_next); + + // progress layout + mProgressLayout = (LinearLayout) findViewById(R.id.wizard_progress); + mProgressLine = findViewById(R.id.wizard_progress_line); + mProgressBar = (ProgressBar) findViewById(R.id.wizard_progress_progressbar); + mProgressImage = (ImageView) findViewById(R.id.wizard_progress_image); + mProgressText = (TextView) findViewById(R.id.wizard_progress_text); + + changeToState(State.START); + } + + private enum ProgressState { + WORKING, ENABLED, DISABLED, ERROR + } + + private void showProgress(ProgressState state, String text) { + switch (state) { + case WORKING: + mProgressBar.setVisibility(View.VISIBLE); + mProgressImage.setVisibility(View.GONE); + break; + case ENABLED: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_enabled)); + break; + case DISABLED: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_disabled)); + break; + case ERROR: + mProgressBar.setVisibility(View.GONE); + mProgressImage.setVisibility(View.VISIBLE); +// mProgressImage.setImageDrawable(getResources().getDrawable( +// R.drawable.status_fail)); + break; + + default: + break; + } + mProgressText.setText(text); + + mProgressLine.setVisibility(View.VISIBLE); + mProgressLayout.setVisibility(View.VISIBLE); + } + + private void hideProgress() { + mProgressLine.setVisibility(View.GONE); + mProgressLayout.setVisibility(View.GONE); + } + + public void nextOnClick(View view) { + // close keyboard + if (getCurrentFocus() != null) { + InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(getCurrentFocus() + .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + + switch (mCurrentState) { + case START: { + RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_start_radio_group); + int selectedId = radioGroup.getCheckedRadioButtonId(); + switch (selectedId) { + case R.id.wizard_start_new_key: { + changeToState(State.CREATE_KEY); + break; + } + case R.id.wizard_start_import: { + changeToState(State.IMPORT_KEY); + break; + } + case R.id.wizard_start_skip: { + finish(); + break; + } + } + + mBackButton.setText(R.string.btn_back); + break; + } + case CREATE_KEY: + EditText nameEdit = (EditText) findViewById(R.id.name); + EditText emailEdit = (EditText) findViewById(R.id.email); + EditText passphraseEdit = (EditText) findViewById(R.id.passphrase); + + if (isEditTextNotEmpty(this, nameEdit) + && isEditTextNotEmpty(this, emailEdit) + && isEditTextNotEmpty(this, passphraseEdit)) { + +// SaveKeyringParcel newKey = new SaveKeyringParcel(); +// newKey.addUserIds.add(nameEdit.getText().toString() + " <" +// + emailEdit.getText().toString() + ">"); + + + AsyncTask<String, Boolean, Boolean> generateTask = new AsyncTask<String, Boolean, Boolean>() { + + @Override + protected void onPreExecute() { + super.onPreExecute(); + + showProgress(ProgressState.WORKING, "generating key..."); + } + + @Override + protected Boolean doInBackground(String... params) { + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + + if (result) { + showProgress(ProgressState.ENABLED, "key generated successfully!"); + + changeToState(State.K9); + } else { + showProgress(ProgressState.ERROR, "error in key gen"); + } + } + + }; + + generateTask.execute(""); + } + break; + case K9: { + RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_k9_radio_group); + int selectedId = radioGroup.getCheckedRadioButtonId(); + switch (selectedId) { + case R.id.wizard_k9_install: { + try { + startActivity(K9_MARKET_INTENT); + } catch (ActivityNotFoundException e) { + Log.e(Constants.TAG, "Activity not found for: " + K9_MARKET_INTENT); + } + break; + } + case R.id.wizard_k9_skip: { + finish(); + break; + } + } + + finish(); + break; + } + default: + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode) { + case REQUEST_CODE_IMPORT: { + if (resultCode == Activity.RESULT_OK) { + // imported now... + changeToState(State.K9); + } else { + // back to start + changeToState(State.START); + } + break; + } + + default: { + super.onActivityResult(requestCode, resultCode, data); + + break; + } + } + } + + public void backOnClick(View view) { + switch (mCurrentState) { + case START: + finish(); + break; + case CREATE_KEY: + changeToState(State.START); + break; + case IMPORT_KEY: + changeToState(State.START); + break; + default: + changeToState(State.START); + break; + } + } + + private void changeToState(State state) { + switch (state) { + case START: { + mCurrentState = State.START; + mStartFragment = StartFragment.newInstance(); + loadFragment(mStartFragment); + mBackButton.setText(android.R.string.cancel); + mNextButton.setText(R.string.btn_next); + break; + } + case CREATE_KEY: { + mCurrentState = State.CREATE_KEY; + mCreateKeyFragment = CreateKeyFragment.newInstance(); + loadFragment(mCreateKeyFragment); + break; + } + case IMPORT_KEY: { + mCurrentState = State.IMPORT_KEY; + Intent intent = new Intent(this, ImportKeysActivity.class); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); + startActivityForResult(intent, REQUEST_CODE_IMPORT); + break; + } + case K9: { + mCurrentState = State.K9; + mBackButton.setEnabled(false); // don't go back to import/create key + mK9Fragment = K9Fragment.newInstance(); + loadFragment(mK9Fragment); + break; + } + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 7a7acfe89..7fc78dc41 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -144,7 +144,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vComment.setVisibility(View.GONE); } - // show small star icon for primary user ids boolean isPrimary = cursor.getInt(mIsPrimary) != 0; boolean isRevoked = cursor.getInt(mIsRevoked) > 0; @@ -185,6 +184,8 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vName.setEnabled(true); vAddress.setEnabled(true); + // verified: has been verified + // isPrimary: show small star icon for primary user ids int verified = cursor.getInt(mVerifiedId); switch (verified) { case Certs.VERIFIED_SECRET: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java new file mode 100644 index 000000000..e6445c074 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * 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 org.sufficientlysecure.keychain.ui.adapter; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; + +import java.util.List; + +public class UserIdsArrayAdapter extends ArrayAdapter<String> { + protected LayoutInflater mInflater; + protected Activity mActivity; + + protected List<String> mData; + + static class ViewHolder { + public TextView vName; + public TextView vAddress; + public TextView vComment; + public ImageView vVerified; + public ImageView vHasChanges; + public CheckBox vCheckBox; + } + + public UserIdsArrayAdapter(Activity activity) { + super(activity, -1); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void setData(List<String> data) { + clear(); + if (data != null) { + this.mData = data; + + // add data to extended ArrayAdapter + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + addAll(data); + } else { + for (String entry : data) { + add(entry); + } + } + } + } + + public List<String> getData() { + return mData; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public View getView(int position, View convertView, ViewGroup parent) { + String entry = mData.get(position); + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.view_key_userids_item, null); + holder.vName = (TextView) convertView.findViewById(R.id.userId); + holder.vAddress = (TextView) convertView.findViewById(R.id.address); + holder.vComment = (TextView) convertView.findViewById(R.id.comment); + holder.vVerified = (ImageView) convertView.findViewById(R.id.certified); + holder.vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes); + holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + // user id + String[] splitUserId = KeyRing.splitUserId(entry); + if (splitUserId[0] != null) { + holder.vName.setText(splitUserId[0]); + } else { + holder.vName.setText(R.string.user_id_no_name); + } + if (splitUserId[1] != null) { + holder.vAddress.setText(splitUserId[1]); + holder.vAddress.setVisibility(View.VISIBLE); + } else { + holder.vAddress.setVisibility(View.GONE); + } + if (splitUserId[2] != null) { + holder.vComment.setText(splitUserId[2]); + holder.vComment.setVisibility(View.VISIBLE); + } else { + holder.vComment.setVisibility(View.GONE); + } + + holder.vCheckBox.setVisibility(View.GONE); + + holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0); + + // all items are "new" + holder.vHasChanges.setVisibility(View.VISIBLE); + + return convertView; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index db7c38e71..c27266e3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -24,17 +24,32 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; -public class AddUserIdDialogFragment extends DialogFragment { +public class AddUserIdDialogFragment extends DialogFragment implements EditText.OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; - public static final int MESSAGE_OK = 1; + public static final int MESSAGE_OKAY = 1; + + public static final String MESSAGE_DATA_USER_ID = "user_id"; private Messenger mMessenger; + EditText mName; + EditText mAddress; + EditText mComment; + /** * Creates new instance of this dialog fragment */ @@ -55,34 +70,75 @@ public class AddUserIdDialogFragment extends DialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { mMessenger = getArguments().getParcelable(ARG_MESSENGER); - CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); -// CharSequence[] array = {"change to primary user id", "revoke"}; -// -// builder.setTitle("select action!"); -// builder.setItems(array, new DialogInterface.OnClickListener() { -// -// @Override -// public void onClick(DialogInterface dialog, int which) { -// switch (which) { -// case 0: -// sendMessageToHandler(MESSAGE_CHANGE_PRIMARY_USER_ID, null); -// break; -// case 1: -// sendMessageToHandler(MESSAGE_REVOKE, null); -// break; -// default: -// break; -// } -// } -// }); -// builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() { -// @Override -// public void onClick(DialogInterface dialog, int id) { -// dismiss(); -// } -// }); - - return builder.show(); + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.add_user_id_dialog, null); + alert.setView(view); + alert.setTitle("Add Identity"); + + mName = (EditText) view.findViewById(R.id.name); + mAddress = (EditText) view.findViewById(R.id.address); + mComment = (EditText) view.findViewById(R.id.comment); + + alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + done(); + } + }); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + + + return alert.show(); + } + + @Override + public void onActivityCreated(Bundle arg0) { + super.onActivityCreated(arg0); + // Show soft keyboard automatically + mName.requestFocus(); + getDialog().getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + mComment.setOnEditorActionListener(this); + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (EditorInfo.IME_ACTION_DONE == actionId) { + done(); + return true; + } + return false; + } + + private void done() { + String name = mName.getText().toString(); + String email = mAddress.getText().toString(); + String comment = mComment.getText().toString(); + + String userId = null; + if (!TextUtils.isEmpty(name)) { + userId = name; + if (!TextUtils.isEmpty(comment)) { + userId += " (" + comment + ")"; + } + if (!TextUtils.isEmpty(email)) { + userId += " <" + email + ">"; + } + } + Bundle data = new Bundle(); + data.putString(MESSAGE_DATA_USER_ID, userId); + sendMessageToHandler(MESSAGE_OKAY, data); + + this.dismiss(); } /** @@ -105,4 +161,5 @@ public class AddUserIdDialogFragment extends DialogFragment { Log.w(Constants.TAG, "Messenger is null!", e); } } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java index 9781dd213..04d4ca5b6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java @@ -119,7 +119,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene mEmail.setAdapter( new ArrayAdapter<String> (this.getContext(), android.R.layout.simple_dropdown_item_1line, - ContactHelper.getMailAccounts(getContext()) + ContactHelper.getPossibleUserEmails(getContext()) )); mEmail.addTextChangedListener(new TextWatcher(){ @Override |