diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget')
2 files changed, 296 insertions, 0 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java new file mode 100644 index 000000000..f1c17bfb5 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -0,0 +1,251 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.app.Activity; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import android.widget.TextView; +import com.tokenautocomplete.FilteredArrayAdapter; +import com.tokenautocomplete.TokenCompleteTextView; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class EncryptKeyCompletionView extends TokenCompleteTextView { + public EncryptKeyCompletionView(Context context) { + super(context); + initView(); + } + + public EncryptKeyCompletionView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public EncryptKeyCompletionView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + swapCursor(null); + setPrefix(getContext().getString(R.string.label_to) + ": "); + allowDuplicates(false); + } + + @Override + protected View getViewForObject(Object object) { + if (object instanceof EncryptionKey) { + LayoutInflater l = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + View view = l.inflate(R.layout.recipient_box_entry, null); + ((TextView) view.findViewById(android.R.id.text1)).setText(((EncryptionKey) object).getPrimary()); + setImageByKey((ImageView) view.findViewById(android.R.id.icon), (EncryptionKey) object); + return view; + } + return null; + } + + private void setImageByKey(ImageView view, EncryptionKey key) { + Bitmap photo = ContactHelper.photoFromFingerprint(getContext().getContentResolver(), key.getFingerprint()); + + if (photo != null) { + view.setImageBitmap(photo); + } else { + view.setImageResource(R.drawable.ic_generic_man); + } + } + + @Override + protected Object defaultObject(String completionText) { + // TODO: We could try to automagically download the key if it's unknown but a key id + /*if (completionText.startsWith("0x")) { + + }*/ + return null; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (getContext() instanceof FragmentActivity) { + ((FragmentActivity) getContext()).getSupportLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() { + @Override + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + return new CursorLoader(getContext(), KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeychainContract.KeyRings.HAS_ENCRYPT, KeychainContract.KeyRings.KEY_ID, KeychainContract.KeyRings.USER_ID, KeychainContract.KeyRings.FINGERPRINT}, + null, null, null); + } + + @Override + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + swapCursor(data); + } + + @Override + public void onLoaderReset(Loader<Cursor> loader) { + swapCursor(null); + } + }); + } + } + + @Override + public void onFocusChanged(boolean hasFocus, int direction, Rect previous) { + super.onFocusChanged(hasFocus, direction, previous); + if (hasFocus) { + ((InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE)) + .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); + } + } + + public void swapCursor(Cursor cursor) { + if (cursor == null) { + setAdapter(new EncryptKeyAdapter(Collections.<EncryptionKey>emptyList())); + return; + } + ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey>(); + while (cursor.moveToNext()) { + try { + if (cursor.getInt(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.HAS_ENCRYPT)) != 0) { + EncryptionKey key = new EncryptionKey(cursor); + keys.add(key); + } + } catch (Exception e) { + Log.w(Constants.TAG, e); + return; + } + } + setAdapter(new EncryptKeyAdapter(keys)); + } + + public class EncryptionKey { + private String mUserIdFull; + private String[] mUserId; + private long mKeyId; + private String mFingerprint; + + public EncryptionKey(String userId, long keyId, String fingerprint) { + this.mUserId = KeyRing.splitUserId(userId); + this.mUserIdFull = userId; + this.mKeyId = keyId; + this.mFingerprint = fingerprint; + } + + public EncryptionKey(Cursor cursor) { + this(cursor.getString(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.USER_ID)), + cursor.getLong(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.KEY_ID)), + PgpKeyHelper.convertFingerprintToHex( + cursor.getBlob(cursor.getColumnIndexOrThrow(KeychainContract.KeyRings.FINGERPRINT)))); + + } + + public EncryptionKey(CachedPublicKeyRing ring) throws PgpGeneralException { + this(ring.getPrimaryUserId(), ring.extractOrGetMasterKeyId(), + PgpKeyHelper.convertFingerprintToHex(ring.getFingerprint())); + } + + public String getUserId() { + return mUserIdFull; + } + + public String getFingerprint() { + return mFingerprint; + } + + public String getPrimary() { + if (mUserId[0] != null && mUserId[2] != null) { + return mUserId[0] + " (" + mUserId[2] + ")"; + } else if (mUserId[0] != null) { + return mUserId[0]; + } else { + return mUserId[1]; + } + } + + public String getSecondary() { + if (mUserId[0] != null) { + return mUserId[1]; + } else { + return getKeyIdHex(); + } + } + + public String getTertiary() { + if (mUserId[0] != null) { + return getKeyIdHex(); + } else { + return null; + } + } + + public long getKeyId() { + return mKeyId; + } + + public String getKeyIdHex() { + return PgpKeyHelper.convertKeyIdToHex(mKeyId); + } + + public String getKeyIdHexShort() { + return PgpKeyHelper.convertKeyIdToHexShort(mKeyId); + } + + @Override + public String toString() { + return Long.toString(mKeyId); + } + } + + private class EncryptKeyAdapter extends FilteredArrayAdapter<EncryptionKey> { + + public EncryptKeyAdapter(List<EncryptionKey> objs) { + super(EncryptKeyCompletionView.this.getContext(), 0, 0, objs); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater l = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + View view; + if (convertView != null) { + view = convertView; + } else { + view = l.inflate(R.layout.recipient_selection_list_entry, null); + } + ((TextView) view.findViewById(android.R.id.title)).setText(getItem(position).getPrimary()); + ((TextView) view.findViewById(android.R.id.text1)).setText(getItem(position).getSecondary()); + ((TextView) view.findViewById(android.R.id.text2)).setText(getItem(position).getTertiary()); + setImageByKey((ImageView) view.findViewById(android.R.id.icon), getItem(position)); + return view; + } + + @Override + protected boolean keepObject(EncryptionKey obj, String mask) { + String m = mask.toLowerCase(); + return obj.getUserId().toLowerCase().contains(m) || + obj.getKeyIdHex().contains(m) || + obj.getKeyIdHexShort().startsWith(m); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java new file mode 100644 index 000000000..516e5ec39 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java @@ -0,0 +1,45 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +public class NoSwipeWrapContentViewPager extends android.support.v4.view.ViewPager { + public NoSwipeWrapContentViewPager(Context context) { + super(context); + } + + public NoSwipeWrapContentViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int height; + View child = getChildAt(getCurrentItem()); + if (child != null) { + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + height = child.getMeasuredHeight(); + } else { + height = 0; + } + + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent arg0) { + // Never allow swiping to switch between pages + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // Never allow swiping to switch between pages + return false; + } +} |