diff options
Diffstat (limited to 'OpenKeychain/src/main')
35 files changed, 897 insertions, 345 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 6a67ac9bf..bed47a44a 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -155,6 +155,7 @@ <!-- Android's Send Action --> <intent-filter android:label="@string/intent_send_encrypt"> <action android:name="android.intent.action.SEND" /> + <action android:name="android.intent.action.SEND_MULTIPLE" /> <category android:name="android.intent.category.DEFAULT" /> 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 e639824ec..1b9ef57b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -21,6 +21,8 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.content.*; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.provider.ContactsContract; @@ -33,6 +35,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; +import java.io.InputStream; import java.util.*; public class ContactHelper { @@ -232,6 +235,17 @@ public class ContactHelper { return null; } + public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { + int rawContactId = findRawContactId(contentResolver, fingerprint); + if (rawContactId == -1) return null; + Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); + Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri); + InputStream photoInputStream = + ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri); + if (photoInputStream == null) return null; + return BitmapFactory.decodeStream(photoInputStream); + } + /** * Write the current Keychain to the contact db */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java index 2898c7030..e42c7987b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/FileHelper.java @@ -23,22 +23,28 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Point; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Messenger; +import android.provider.DocumentsContract; import android.provider.OpenableColumns; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; import java.io.File; +import java.text.DecimalFormat; public class FileHelper { @@ -182,6 +188,41 @@ public class FileHelper { return filename; } + public static long getFileSize(Context context, Uri uri) { + long size = -1; + try { + Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null); + + if (cursor != null) { + if (cursor.moveToNext()) { + size = cursor.getLong(0); + } + cursor.close(); + } + } catch (Exception ignored) { + // This happens in rare cases (eg: document deleted since selection) and should not cause a failure + } + return size; + } + + /** + * Retrieve thumbnail of file, document api feature and thus KitKat only + */ + public static Bitmap getThumbnail(Context context, Uri uri, Point size) { + if (Constants.KITKAT) { + return DocumentsContract.getDocumentThumbnail(context.getContentResolver(), uri, size, null); + } else { + return null; + } + } + + public static String readableFileSize(long size) { + if(size <= 0) return "0"; + final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; + int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); + return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } + public static interface FileDialogCallback { public void onFileSelected(File file, boolean checked); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java index 52ca71679..bc7221d13 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/CachedPublicKeyRing.java @@ -1,5 +1,6 @@ package org.sufficientlysecure.keychain.provider; +import android.database.Cursor; import android.net.Uri; import org.sufficientlysecure.keychain.Constants; @@ -33,6 +34,7 @@ public class CachedPublicKeyRing extends KeyRing { mUri = uri; } + @Override public long getMasterKeyId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -59,6 +61,17 @@ public class CachedPublicKeyRing extends KeyRing { return getMasterKeyId(); } + public byte[] getFingerprint() throws PgpGeneralException { + try { + Object data = mProviderHelper.getGenericData(mUri, + KeychainContract.KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); + return (byte[]) data; + } catch (ProviderHelper.NotFoundException e) { + throw new PgpGeneralException(e); + } + } + + @Override public String getPrimaryUserId() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -70,6 +83,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public boolean isRevoked() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -81,6 +95,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public boolean canCertify() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -92,17 +107,28 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public long getEncryptId() throws PgpGeneralException { try { - Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, - ProviderHelper.FIELD_TYPE_INTEGER); - return (Long) data; - } catch(ProviderHelper.NotFoundException e) { + Cursor subkeys = getSubkeys(); + if (subkeys != null) { + try { + while (subkeys.moveToNext()) { + if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_ENCRYPT)) != 0) { + return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); + } + } + } finally { + subkeys.close(); + } + } + } catch(Exception e) { throw new PgpGeneralException(e); } + throw new PgpGeneralException("No encrypt key found"); } + @Override public boolean hasEncrypt() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -114,17 +140,28 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public long getSignId() throws PgpGeneralException { try { - Object data = mProviderHelper.getGenericData(mUri, - KeychainContract.KeyRings.MASTER_KEY_ID, - ProviderHelper.FIELD_TYPE_INTEGER); - return (Long) data; - } catch(ProviderHelper.NotFoundException e) { + Cursor subkeys = getSubkeys(); + if (subkeys != null) { + try { + while (subkeys.moveToNext()) { + if (subkeys.getInt(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.CAN_SIGN)) != 0) { + return subkeys.getLong(subkeys.getColumnIndexOrThrow(KeychainContract.Keys.KEY_ID)); + } + } + } finally { + subkeys.close(); + } + } + } catch(Exception e) { throw new PgpGeneralException(e); } + throw new PgpGeneralException("No sign key found"); } + @Override public boolean hasSign() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -136,6 +173,7 @@ public class CachedPublicKeyRing extends KeyRing { } } + @Override public int getVerified() throws PgpGeneralException { try { Object data = mProviderHelper.getGenericData(mUri, @@ -156,6 +194,10 @@ public class CachedPublicKeyRing extends KeyRing { } catch(ProviderHelper.NotFoundException e) { throw new PgpGeneralException(e); } + } + private Cursor getSubkeys() throws PgpGeneralException { + Uri keysUri = KeychainContract.Keys.buildKeysUri(Long.toString(extractOrGetMasterKeyId())); + return mProviderHelper.getContentResolver().query(keysUri, null, null, null, null); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 28495d51d..4bf3a38a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1034,4 +1034,8 @@ public class ProviderHelper { } } } + + public ContentResolver getContentResolver() { + return mContentResolver; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index c77fe9ab8..5542cccd1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -21,14 +21,21 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; +import android.view.Menu; +import android.view.MenuItem; +import android.view.ViewGroup; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.util.Log; +import java.util.ArrayList; + public class EncryptActivity extends DrawerActivity implements EncryptSymmetricFragment.OnSymmetricKeySelection, EncryptAsymmetricFragment.OnAsymmetricKeySelection, @@ -49,7 +56,7 @@ public class EncryptActivity extends DrawerActivity implements // view ViewPager mViewPagerMode; - PagerTabStrip mPagerTabStripMode; + //PagerTabStrip mPagerTabStripMode; PagerTabStripAdapter mTabsAdapterMode; ViewPager mViewPagerContent; PagerTabStrip mPagerTabStripContent; @@ -74,6 +81,9 @@ public class EncryptActivity extends DrawerActivity implements private long mSigningKeyId = Constants.key.none; private String mPassphrase; private String mPassphraseAgain; + private int mCurrentMode = PAGER_MODE_ASYMMETRIC; + private boolean mUseArmor; + private boolean mDeleteAfterEncrypt = false; @Override public void onSigningKeySelected(long signingKeyId) { @@ -102,7 +112,7 @@ public class EncryptActivity extends DrawerActivity implements @Override public boolean isModeSymmetric() { - return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); + return PAGER_MODE_SYMMETRIC == mCurrentMode; } @Override @@ -130,10 +140,19 @@ public class EncryptActivity extends DrawerActivity implements return mPassphraseAgain; } + @Override + public boolean isUseArmor() { + return mUseArmor; + } + + @Override + public boolean isDeleteAfterEncrypt() { + return mDeleteAfterEncrypt; + } private void initView() { mViewPagerMode = (ViewPager) findViewById(R.id.encrypt_pager_mode); - mPagerTabStripMode = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_mode); + //mPagerTabStripMode = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_mode); mViewPagerContent = (ViewPager) findViewById(R.id.encrypt_pager_content); mPagerTabStripContent = (PagerTabStrip) findViewById(R.id.encrypt_pager_tab_strip_content); @@ -172,6 +191,37 @@ public class EncryptActivity extends DrawerActivity implements mTabsAdapterContent.addTab(EncryptFileFragment.class, mFileFragmentBundle, getString(R.string.label_file)); mViewPagerContent.setCurrentItem(mSwitchToContent); + + mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.encrypt_activity, menu); + menu.findItem(R.id.check_use_armor).setChecked(mUseArmor); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.isCheckable()) { + item.setChecked(!item.isChecked()); + } + switch (item.getItemId()) { + case R.id.check_use_symmetric: + mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; + mViewPagerMode.setCurrentItem(mSwitchToMode); + break; + case R.id.check_use_armor: + mUseArmor = item.isChecked(); + break; + case R.id.check_delete_after_encrypt: + mDeleteAfterEncrypt = item.isChecked(); + break; + default: + return super.onOptionsItemSelected(item); + } + return true; } /** @@ -183,12 +233,16 @@ public class EncryptActivity extends DrawerActivity implements String action = intent.getAction(); Bundle extras = intent.getExtras(); String type = intent.getType(); - Uri uri = intent.getData(); + ArrayList<Uri> uris = new ArrayList<Uri>(); if (extras == null) { extras = new Bundle(); } + if (intent.getData() != null) { + uris.add(intent.getData()); + } + /* * Android's Action */ @@ -206,14 +260,19 @@ public class EncryptActivity extends DrawerActivity implements } } else { // Files via content provider, override uri and action - uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); + uris.clear(); + uris.add(intent.<Uri>getParcelableExtra(Intent.EXTRA_STREAM)); action = ACTION_ENCRYPT; } } + if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { + uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + action = ACTION_ENCRYPT; + } + if (extras.containsKey(EXTRA_ASCII_ARMOR)) { - boolean requestAsciiArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, true); - mFileFragmentBundle.putBoolean(EncryptFileFragment.ARG_ASCII_ARMOR, requestAsciiArmor); + mUseArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, true); } String textData = extras.getString(EXTRA_TEXT); @@ -235,9 +294,9 @@ public class EncryptActivity extends DrawerActivity implements // encrypt text based on given extra mMessageFragmentBundle.putString(EncryptMessageFragment.ARG_TEXT, textData); mSwitchToContent = PAGER_CONTENT_MESSAGE; - } else if (ACTION_ENCRYPT.equals(action) && uri != null) { + } else if (ACTION_ENCRYPT.equals(action) && uris != null && !uris.isEmpty()) { // encrypt file based on Uri - mFileFragmentBundle.putParcelable(EncryptFileFragment.ARG_URI, uri); + mFileFragmentBundle.putParcelableArrayList(EncryptFileFragment.ARG_URIS, uris); mSwitchToContent = PAGER_CONTENT_FILE; } else { Log.e(Constants.TAG, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index ca2ee3b55..6d649c32e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -28,4 +28,6 @@ public interface EncryptActivityInterface { public String getPassphrase(); public String getPassphraseAgain(); + boolean isUseArmor(); + boolean isDeleteAfterEncrypt(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index be845f05e..dc9cfe72e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -19,25 +19,30 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.content.Intent; +import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.TextView; -import android.widget.Button; +import android.widget.*; +import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; import org.sufficientlysecure.keychain.util.Log; -import java.util.Vector; +import java.util.*; public class EncryptAsymmetricFragment extends Fragment { public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; @@ -51,10 +56,8 @@ public class EncryptAsymmetricFragment extends Fragment { OnAsymmetricKeySelection mKeySelectionListener; // view - private Button mSelectKeysButton; private CheckBox mSign; - private TextView mMainUserId; - private TextView mMainUserIdRest; + private EncryptKeyCompletionView mEncryptKeyView; // model private long mSecretKeyId = Constants.key.none; @@ -108,15 +111,7 @@ public class EncryptAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSelectKeysButton = (Button) view.findViewById(R.id.btn_selectEncryptKeys); mSign = (CheckBox) view.findViewById(R.id.sign); - mMainUserId = (TextView) view.findViewById(R.id.mainUserId); - mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - mSelectKeysButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - selectPublicKeys(); - } - }); mSign.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { CheckBox checkBox = (CheckBox) v; @@ -127,6 +122,7 @@ public class EncryptAsymmetricFragment extends Fragment { } } }); + mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); return view; } @@ -140,6 +136,40 @@ public class EncryptAsymmetricFragment extends Fragment { mProviderHelper = new ProviderHelper(getActivity()); + getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() { + @Override + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + return new CursorLoader(getActivity(), KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeyRings.HAS_ENCRYPT, KeyRings.KEY_ID, KeyRings.USER_ID, KeyRings.FINGERPRINT}, + null, null, null); + } + + @Override + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + mEncryptKeyView.fromCursor(data); + } + + @Override + public void onLoaderReset(Loader<Cursor> loader) { + mEncryptKeyView.fromCursor(null); + } + }); + mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { + @Override + public void onTokenAdded(Object token) { + if (token instanceof EncryptKeyCompletionView.EncryptionKey) { + updateEncryptionKeys(); + } + } + + @Override + public void onTokenRemoved(Object token) { + if (token instanceof EncryptKeyCompletionView.EncryptionKey) { + updateEncryptionKeys(); + } + } + }); + // preselect keys given by arguments (given by Intent to EncryptActivity) preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); } @@ -168,44 +198,31 @@ public class EncryptAsymmetricFragment extends Fragment { } if (preselectedEncryptionKeyIds != null) { - Vector<Long> goodIds = new Vector<Long>(); - Vector<String> goodUserIds = new Vector<String>(); for (long preselectedId : preselectedEncryptionKeyIds) { try { CachedPublicKeyRing ring = providerHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(preselectedId)); - long id = ring.getMasterKeyId(); - ring.getSplitPrimaryUserId(); - goodUserIds.add(ring.getPrimaryUserId()); - goodIds.add(id); + mEncryptKeyView.addObject(mEncryptKeyView.new EncryptionKey(ring)); } catch (PgpGeneralException e) { Log.e(Constants.TAG, "key not found!", e); } } - if (goodIds.size() > 0) { - long[] keyIds = new long[goodIds.size()]; - for (int i = 0; i < goodIds.size(); ++i) { - keyIds[i] = goodIds.get(i); - } - setEncryptionKeyIds(keyIds); - setEncryptionUserIds(goodUserIds.toArray(new String[goodUserIds.size()])); - } + updateEncryptionKeys(); } } private void updateView() { - if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { + /*if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { mSelectKeysButton.setText(getString(R.string.select_keys_button_default)); } else { mSelectKeysButton.setText(getResources().getQuantityString( R.plurals.select_keys_button, mEncryptionKeyIds.length, mEncryptionKeyIds.length)); - } + }*/ + /* if (mSecretKeyId == Constants.key.none) { mSign.setChecked(false); - mMainUserId.setText(""); - mMainUserIdRest.setText(""); } else { // See if we can get a user_id from a unified query String[] userId; @@ -216,7 +233,7 @@ public class EncryptAsymmetricFragment extends Fragment { userId = null; } if (userId != null && userId[0] != null) { - mMainUserId.setText(String.format("%#16x", Long.parseLong(userId[0]))); + mMainUserId.setText(userId[0]); } else { mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); } @@ -227,6 +244,26 @@ public class EncryptAsymmetricFragment extends Fragment { } mSign.setChecked(true); } + */ + } + + private void updateEncryptionKeys() { + List<Object> objects = mEncryptKeyView.getObjects(); + List<Long> keyIds = new ArrayList<Long>(); + List<String> userIds = new ArrayList<String>(); + for (Object object : objects) { + if (object instanceof EncryptKeyCompletionView.EncryptionKey) { + keyIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getKeyId()); + userIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getUserId()); + } + } + long[] keyIdsArr = new long[keyIds.size()]; + Iterator<Long> iterator = keyIds.iterator(); + for (int i = 0; i < keyIds.size(); i++) { + keyIdsArr[i] = iterator.next(); + } + setEncryptionKeyIds(keyIdsArr); + setEncryptionUserIds(userIds.toArray(new String[userIds.size()])); } private void selectPublicKeys() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 3111e5c3e..350bc03aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -20,6 +20,8 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Point; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -29,15 +31,13 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.Spinner; -import android.widget.TextView; +import android.widget.*; import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -45,18 +45,18 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.io.File; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; public class EncryptFileFragment extends Fragment { - public static final String ARG_URI = "uri"; - public static final String ARG_ASCII_ARMOR = "ascii_armor"; + public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; @@ -64,16 +64,14 @@ public class EncryptFileFragment extends Fragment { private EncryptActivityInterface mEncryptInterface; // view - private CheckBox mAsciiArmor = null; private Spinner mFileCompression = null; - private TextView mFilename = null; - private CheckBox mDeleteAfter = null; private View mShareFile; private View mEncryptFile; + private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); // model - private Uri mInputUri = null; - private Uri mOutputUri = null; + private ArrayList<Uri> mInputUri = new ArrayList<Uri>(); + private ArrayList<Uri> mOutputUri = new ArrayList<Uri>(); @Override public void onAttach(Activity activity) { @@ -107,17 +105,33 @@ public class EncryptFileFragment extends Fragment { } }); - mFilename = (TextView) view.findViewById(R.id.filename); - view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { + //mFilename = (TextView) view.findViewById(R.id.filename); + //view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { + // public void onClick(View v) { + // if (Constants.KITKAT) { + // FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); + // } else { + // FileHelper.openFile(EncryptFileFragment.this, + // mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); + // } + // } + //}); + + View addFile = inflater.inflate(R.layout.file_list_entry_add, null); + addFile.setOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { - FileHelper.openFile(EncryptFileFragment.this, mInputUri, "*/*", - REQUEST_CODE_INPUT); + FileHelper.openFile(EncryptFileFragment.this, + mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); } } }); + ListView listView = (ListView) view.findViewById(R.id.selected_files_list); + listView.addFooterView(addFile); + listView.setAdapter(mAdapter); mFileCompression = (Spinner) view.findViewById(R.id.fileCompression); Choice[] choices = new Choice[]{ @@ -143,11 +157,6 @@ public class EncryptFileFragment extends Fragment { } } - mDeleteAfter = (CheckBox) view.findViewById(R.id.deleteAfterEncryption); - - mAsciiArmor = (CheckBox) view.findViewById(R.id.asciiArmor); - mAsciiArmor.setChecked(Preferences.getPreferences(getActivity()).getDefaultAsciiArmor()); - return view; } @@ -155,43 +164,57 @@ public class EncryptFileFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - setInputUri(getArguments().<Uri>getParcelable(ARG_URI)); - boolean asciiArmor = getArguments().getBoolean(ARG_ASCII_ARMOR); - if (asciiArmor) { - mAsciiArmor.setChecked(true); + addInputUris(getArguments().<Uri>getParcelableArrayList(ARG_URIS)); + } + + private void addInputUris(List<Uri> uris) { + if (uris != null) { + for (Uri uri : uris) { + addInputUri(uri); + } } } - private void setInputUri(Uri inputUri) { + private void addInputUri(Uri inputUri) { if (inputUri == null) { - mInputUri = null; - mFilename.setText(""); return; } - mInputUri = inputUri; - mFilename.setText(FileHelper.getFilename(getActivity(), mInputUri)); + mInputUri.add(inputUri); + mAdapter.notifyDataSetChanged(); + } + + private void delInputUri(int position) { + mInputUri.remove(position); + mAdapter.notifyDataSetChanged(); } private void showOutputFileDialog() { + if (mInputUri.size() > 1 || mInputUri.isEmpty()) { + throw new IllegalStateException(); + } + Uri inputUri = mInputUri.get(0); if (!Constants.KITKAT) { - File file = new File(mInputUri.getPath()); + File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; - String targetName = FileHelper.getFilename( - getActivity(), mInputUri) + (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); + String targetName = FileHelper.getFilename(getActivity(), inputUri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); File targetFile = new File(parentDir, targetName); FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file), getString(R.string.specify_file_to_encrypt_to), targetFile, REQUEST_CODE_OUTPUT); } else { - FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), mInputUri) + - (mAsciiArmor.isChecked() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT); + FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), inputUri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT); } } private void encryptClicked(boolean share) { - if (mInputUri == null) { + if (mInputUri.isEmpty()) { AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); return; + } else if (mInputUri.size() > 1 && !share) { + AppMsg.makeText(getActivity(), "TODO", AppMsg.STYLE_ALERT).show(); // TODO + return; } if (mEncryptInterface.isModeSymmetric()) { @@ -244,17 +267,20 @@ public class EncryptFileFragment extends Fragment { } if (share) { - String targetName = FileHelper.getFilename(getActivity(), mInputUri) + - (mAsciiArmor.isChecked() ? ".asc" : ".gpg"); - mOutputUri = TemporaryStorageProvider.createFile(getActivity(), targetName); + mOutputUri.clear(); + for (Uri uri : mInputUri) { + String targetName = FileHelper.getFilename(getActivity(), uri) + + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); + mOutputUri.add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + } encryptStart(true); - } else { + } else if (mInputUri.size() == 1) { showOutputFileDialog(); } } private void encryptStart(final boolean share) { - if (mInputUri == null || mOutputUri == null) { + if (mInputUri == null || mOutputUri == null || mInputUri.size() != mOutputUri.size()) { throw new IllegalStateException("Something went terribly wrong if this happens!"); } @@ -268,11 +294,11 @@ public class EncryptFileFragment extends Fragment { Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUri); - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); - data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUri); if (mEncryptInterface.isModeSymmetric()) { Log.d(Constants.TAG, "Symmetric encryption enabled!"); @@ -288,8 +314,7 @@ public class EncryptFileFragment extends Fragment { mEncryptInterface.getEncryptionKeys()); } - boolean useAsciiArmor = mAsciiArmor.isChecked(); - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, useAsciiArmor); + data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mEncryptInterface.isUseArmor()); int compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); @@ -307,18 +332,25 @@ public class EncryptFileFragment extends Fragment { AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful, AppMsg.STYLE_INFO).show(); - if (mDeleteAfter.isChecked()) { + if (mEncryptInterface.isDeleteAfterEncrypt()) { // Create and show dialog to delete original file - DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); + /*DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - setInputUri(null); + setInputUri(null);*/ } if (share) { // Share encrypted file - Intent sendFileIntent = new Intent(Intent.ACTION_SEND); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); + Intent sendFileIntent; + if (mOutputUri.size() == 1) { + sendFileIntent = new Intent(Intent.ACTION_SEND); + sendFileIntent.setType("*/*"); + sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri.get(0)); + } else { + sendFileIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); + sendFileIntent.setType("*/*"); + sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); + } if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { Set<String> users = new HashSet<String>(); for (String user : mEncryptInterface.getEncryptionUsers()) { @@ -352,14 +384,14 @@ public class EncryptFileFragment extends Fragment { switch (requestCode) { case REQUEST_CODE_INPUT: { if (resultCode == Activity.RESULT_OK && data != null) { - setInputUri(data.getData()); + addInputUri(data.getData()); } return; } case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { - mOutputUri = data.getData(); + mOutputUri.add(data.getData()); encryptStart(false); } return; @@ -372,4 +404,52 @@ public class EncryptFileFragment extends Fragment { } } } + + private class SelectedFilesAdapter extends BaseAdapter { + @Override + public int getCount() { + return mInputUri.size(); + } + + @Override + public Object getItem(int position) { + return mInputUri.get(position); + } + + @Override + public long getItemId(int position) { + return getItem(position).hashCode(); + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + View view; + if (convertView == null) { + view = getActivity().getLayoutInflater().inflate(R.layout.file_list_entry, null); + } else { + view = convertView; + } + ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mInputUri.get(position))); + long size = FileHelper.getFileSize(getActivity(), mInputUri.get(position)); + if (size == -1) { + ((TextView) view.findViewById(R.id.filesize)).setText(""); + } else { + ((TextView) view.findViewById(R.id.filesize)).setText(FileHelper.readableFileSize(size)); + } + view.findViewById(R.id.action_remove_file_from_list).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + delInputUri(position); + } + }); + int px = OtherHelper.dpToPx(getActivity(), 48); + Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mInputUri.get(position), new Point(px, px)); + if (bitmap != null) { + ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap); + } else { + ((ImageView) view.findViewById(R.id.thumbnail)).setImageResource(R.drawable.ic_doc_generic_am); + } + return view; + } + } } 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..4566e37fd --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -0,0 +1,204 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.app.Activity; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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() { + fromCursor(null); + setPrefix(getContext().getString(R.string.label_to) + ": "); + allowDuplicates(false); + } + + private EncryptKeyAdapter mAdapter; + + @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; + } + + public void fromCursor(Cursor cursor) { + if (cursor == null) { + setAdapter(new EncryptKeyAdapter(Collections.<EncryptionKey>emptyList())); + return; + } + ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey>(); + cursor.moveToFirst(); + 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 mUserId; + private long mKeyId; + private String mFingerprint; + + public EncryptionKey(String userId, long keyId, String fingerprint) { + this.mUserId = 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 mUserId; + } + + public String getFingerprint() { + return mFingerprint; + } + + public String getPrimary() { + String[] userId = KeyRing.splitUserId(mUserId); + if (userId[0] != null && userId[2] != null) { + return userId[0] + " (" + userId[2] + ")"; + } else if (userId[0] != null) { + return userId[0]; + } else { + return userId[1]; + } + } + + public String getSecondary() { + String[] userId = KeyRing.splitUserId(mUserId); + if (userId[0] != null) { + return userId[1] + " (" + getKeyIdHexShort() + ")"; + } else { + return getKeyIdHex(); + } + } + + 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()); + 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..08f071fb2 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NoSwipeWrapContentViewPager.java @@ -0,0 +1,44 @@ +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 = 0; + for(int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int h = child.getMeasuredHeight(); + if(h > height) height = h; + } + + 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; + } +} diff --git a/OpenKeychain/src/main/res/drawable-hdpi/attachment_bg_holo.9.png b/OpenKeychain/src/main/res/drawable-hdpi/attachment_bg_holo.9.png Binary files differnew file mode 100644 index 000000000..3cbdd667b --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/attachment_bg_holo.9.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_doc_generic_am.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_doc_generic_am.png Binary files differnew file mode 100644 index 000000000..55b9b7d3c --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_doc_generic_am.png diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_generic_man.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_generic_man.png Binary files differnew file mode 100644 index 000000000..b6b3129f5 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_generic_man.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/attachment_bg_holo.9.png b/OpenKeychain/src/main/res/drawable-mdpi/attachment_bg_holo.9.png Binary files differnew file mode 100644 index 000000000..bb9214b6a --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/attachment_bg_holo.9.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_doc_generic_am.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_doc_generic_am.png Binary files differnew file mode 100644 index 000000000..a1bd14eaf --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_doc_generic_am.png diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_generic_man.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_generic_man.png Binary files differnew file mode 100644 index 000000000..f763dd259 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_generic_man.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/attachment_bg_holo.9.png b/OpenKeychain/src/main/res/drawable-xhdpi/attachment_bg_holo.9.png Binary files differnew file mode 100644 index 000000000..1f4b25d21 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/attachment_bg_holo.9.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_doc_generic_am.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_doc_generic_am.png Binary files differnew file mode 100644 index 000000000..e05c4b48d --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_doc_generic_am.png diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_generic_man.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_generic_man.png Binary files differnew file mode 100644 index 000000000..212293db0 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_generic_man.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/attachment_bg_holo.9.png b/OpenKeychain/src/main/res/drawable-xxhdpi/attachment_bg_holo.9.png Binary files differnew file mode 100644 index 000000000..13855a2b1 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/attachment_bg_holo.9.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_doc_generic_am.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_doc_generic_am.png Binary files differnew file mode 100644 index 000000000..c09886632 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_doc_generic_am.png diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_generic_man.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_generic_man.png Binary files differnew file mode 100644 index 000000000..130c670c9 --- /dev/null +++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_generic_man.png diff --git a/OpenKeychain/src/main/res/layout/encrypt_activity.xml b/OpenKeychain/src/main/res/layout/encrypt_activity.xml index 65c2ee8fd..839bddc75 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_activity.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_activity.xml @@ -1,10 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v4.widget.FixedDrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" - xmlns:fontawesometext="http://schemas.android.com/apk/res-auto" - android:id="@+id/drawer_layout" - android:layout_width="match_parent" - android:layout_height="match_parent"> +<android.support.v4.widget.FixedDrawerLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/drawer_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.EncryptActivity"> <include layout="@layout/encrypt_content"/> diff --git a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml index cde92b477..284fdd9ce 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml @@ -9,69 +9,15 @@ android:paddingRight="16dp" android:paddingLeft="16dp"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <CheckBox + <CheckBox android:id="@+id/sign" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:text="@string/label_sign" /> + android:text="@string/label_sign"/> - <LinearLayout + <org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView + android:id="@+id/recipient_list" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:paddingLeft="16dp" - android:paddingRight="4dip"> - - <TextView - android:id="@+id/mainUserId" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="right" - android:ellipsize="end" - android:singleLine="true" - android:text="" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <TextView - android:id="@+id/mainUserIdRest" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="right" - android:ellipsize="end" - android:singleLine="true" - android:text="" - android:textAppearance="?android:attr/textAppearanceSmall" /> - </LinearLayout> - </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <TextView - android:id="@+id/label_selectPublicKeys" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_weight="1" - android:text="@string/label_select_public_keys" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <Button - android:id="@+id/btn_selectEncryptKeys" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_margin="4dp" - android:text="@string/select_keys_button_default" - android:background="@drawable/button_edgy" - android:drawableLeft="@drawable/ic_action_person" /> - </LinearLayout> + android:layout_height="wrap_content"/> </LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_content.xml b/OpenKeychain/src/main/res/layout/encrypt_content.xml index e719d07e1..ec71b25e5 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_content.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_content.xml @@ -6,19 +6,12 @@ android:layout_height="match_parent" android:orientation="vertical"> - <android.support.v4.view.ViewPager + <org.sufficientlysecure.keychain.ui.widget.NoSwipeWrapContentViewPager android:id="@+id/encrypt_pager_mode" android:layout_width="match_parent" - android:layout_height="150dp"> + android:layout_height="wrap_content"> - <android.support.v4.view.PagerTabStrip - android:id="@+id/encrypt_pager_tab_strip_mode" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="top" - android:background="@color/emphasis" - android:textColor="#fff" /> - </android.support.v4.view.ViewPager> + </org.sufficientlysecure.keychain.ui.widget.NoSwipeWrapContentViewPager> <android.support.v4.view.ViewPager android:id="@+id/encrypt_pager_content" @@ -30,8 +23,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" - android:background="@color/emphasis" - android:textColor="#fff" /> + android:textColor="@color/emphasis" /> </android.support.v4.view.ViewPager> </LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml b/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml index 8394fd4fe..67f7032c1 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_content_adv_settings.xml @@ -21,30 +21,4 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical"/> </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <CheckBox - android:id="@+id/deleteAfterEncryption" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:text="@string/label_delete_after_encryption"/> - </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <CheckBox - android:id="@+id/asciiArmor" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:text="@string/label_ascii_armor"/> - </LinearLayout> </merge> diff --git a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml index c97069e67..d52097433 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml @@ -1,46 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingLeft="16dp" - android:paddingRight="16dp" - android:orientation="vertical"> - - <LinearLayout android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - android:orientation="horizontal" - - android:id="@+id/btn_browse" - android:clickable="true" - style="@style/SelectableItem"> - - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:paddingLeft="8dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/label_file_colon" - android:gravity="center_vertical"/> - - <TextView - android:id="@+id/filename" - android:paddingLeft="8dp" - android:paddingRight="8dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:hint="@string/filemanager_title_open" - android:drawableRight="@drawable/ic_action_collection" - android:drawablePadding="8dp" - android:gravity="center_vertical"/> - </LinearLayout> + android:layout_height="wrap_content" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:orientation="vertical"> <View android:layout_width="match_parent" @@ -48,73 +17,66 @@ android:background="?android:attr/listDivider" android:layout_marginBottom="8dp"/> - <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - custom:foldedLabel="@string/btn_encryption_advanced_settings_show" - custom:unFoldedLabel="@string/btn_encryption_advanced_settings_hide" - custom:foldedIcon="fa-chevron-right" - custom:unFoldedIcon="fa-chevron-down"> + <ListView + android:id="@+id/selected_files_list" + android:dividerHeight="4dip" + android:divider="@android:color/transparent" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1"/> - <include layout="@layout/encrypt_content_adv_settings" /> + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider" + android:layout_marginBottom="8dp"/> - </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout> + <include layout="@layout/encrypt_content_adv_settings" /> - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="match_parent"> + <View + android:layout_width="match_parent" + android:layout_height="1dip" + android:background="?android:attr/listDivider"/> + <LinearLayout + android:id="@+id/action_encrypt_share" + android:paddingLeft="8dp" + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:layout_marginBottom="8dp" + android:clickable="true" + style="@style/SelectableItem" + android:orientation="horizontal"> - <LinearLayout - android:id="@+id/action_encrypt_share" + <TextView android:paddingLeft="8dp" - android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_marginBottom="8dp" - android:clickable="true" - style="@style/SelectableItem" - android:orientation="horizontal"> - - <TextView - android:paddingLeft="8dp" - android:paddingRight="8dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:layout_width="0dip" - android:layout_height="match_parent" - android:text="@string/btn_encrypt_share_file" - android:layout_weight="1" - android:drawableRight="@drawable/ic_action_share" - android:drawablePadding="8dp" - android:gravity="center_vertical"/> - - <View - android:layout_width="1dip" - android:layout_height="match_parent" - android:gravity="right" - android:layout_marginBottom="8dp" - android:layout_marginTop="8dp" - android:background="?android:attr/listDivider"/> - - <ImageButton - android:id="@+id/action_encrypt_file" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:padding="8dp" - android:src="@drawable/ic_action_save" - android:layout_gravity="center_vertical" - style="@style/SelectableItem"/> - - </LinearLayout> + android:paddingRight="8dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="0dip" + android:layout_height="match_parent" + android:text="@string/btn_encrypt_share_file" + android:layout_weight="1" + android:drawableRight="@drawable/ic_action_share" + android:drawablePadding="8dp" + android:gravity="center_vertical"/> <View - android:layout_width="match_parent" - android:layout_height="1dip" - android:background="?android:attr/listDivider" - android:layout_above="@+id/action_encrypt_share"/> + android:layout_width="1dip" + android:layout_height="match_parent" + android:gravity="right" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:background="?android:attr/listDivider"/> + + <ImageButton + android:id="@+id/action_encrypt_file" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:padding="8dp" + android:src="@drawable/ic_action_save" + android:layout_gravity="center_vertical" + style="@style/SelectableItem"/> - </RelativeLayout> + </LinearLayout> </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_symmetric_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_symmetric_fragment.xml index 89381e499..699f991a7 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_symmetric_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_symmetric_fragment.xml @@ -1,52 +1,46 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/modeSymmetric" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" + android:stretchColumns="1" android:paddingTop="4dp" android:paddingBottom="4dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:orientation="vertical"> + android:layout_centerVertical="true"> - <TableLayout - android:id="@+id/modeSymmetric" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:stretchColumns="1" - android:layout_centerVertical="true"> + <TableRow> - <TableRow> + <TextView + android:id="@+id/label_passphrase" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingRight="8dp" + android:text="@string/label_passphrase" + android:textAppearance="?android:attr/textAppearanceMedium" /> - <TextView - android:id="@+id/label_passphrase" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="8dp" - android:text="@string/label_passphrase" - android:textAppearance="?android:attr/textAppearanceMedium" /> + <EditText + android:id="@+id/passphrase" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" /> + </TableRow> - <EditText - android:id="@+id/passphrase" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inputType="textPassword" /> - </TableRow> + <TableRow> - <TableRow> + <TextView + android:id="@+id/label_passphraseAgain" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingRight="8dp" + android:text="@string/label_passphrase_again" + android:textAppearance="?android:attr/textAppearanceMedium" /> - <TextView - android:id="@+id/label_passphraseAgain" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="8dp" - android:text="@string/label_passphrase_again" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <EditText - android:id="@+id/passphraseAgain" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inputType="textPassword" /> - </TableRow> - </TableLayout> -</RelativeLayout>
\ No newline at end of file + <EditText + android:id="@+id/passphraseAgain" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" /> + </TableRow> +</TableLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/file_list_entry.xml b/OpenKeychain/src/main/res/layout/file_list_entry.xml new file mode 100644 index 000000000..f6fde2447 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/file_list_entry.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="48dip" + android:background="@drawable/attachment_bg_holo"> + + <ImageView + android:id="@+id/thumbnail" + android:layout_alignParentLeft="true" + android:layout_centerVertical="true" + android:scaleType="center" + android:layout_width="48dip" + android:layout_height="48dip"/> + + <LinearLayout + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@+id/thumbnail" + android:layout_centerVertical="true"> + + <TextView + android:id="@+id/filename" + android:layout_marginLeft="8dip" + android:layout_marginRight="32dip" + android:maxLines="1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="?android:attr/textColorSecondary" + android:textAppearance="?android:attr/textAppearanceSmall" + android:ellipsize="end"/> + + <TextView + android:id="@+id/filesize" + android:layout_marginLeft="8dip" + android:layout_marginRight="32dip" + android:maxLines="1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="?android:attr/textColorTertiary" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textSize="12sp" + android:ellipsize="end"/> + + </LinearLayout> + + <ImageButton + android:id="@+id/action_remove_file_from_list" + android:layout_width="48dip" + android:layout_height="48dip" + android:layout_alignParentRight="true" + android:paddingRight="16dip" + android:paddingLeft="16dip" + android:src="@drawable/ic_action_cancel" + android:clickable="true" + android:layout_centerVertical="true" + style="@style/SelectableItem"/> +</RelativeLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/file_list_entry_add.xml b/OpenKeychain/src/main/res/layout/file_list_entry_add.xml new file mode 100644 index 000000000..2f24227fa --- /dev/null +++ b/OpenKeychain/src/main/res/layout/file_list_entry_add.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:padding="4dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clickable="true" + style="@style/SelectableItem"> + <TextView + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center" + android:text="Add file(s)" + android:drawableLeft="@drawable/ic_action_collection" + android:drawablePadding="8dp" + android:gravity="center"/> +</FrameLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/recipient_box_entry.xml b/OpenKeychain/src/main/res/layout/recipient_box_entry.xml new file mode 100644 index 000000000..a7862c515 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/recipient_box_entry.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/attachment_bg_holo"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="4dip" + android:id="@android:id/text1" + android:layout_gravity="center_vertical"/> + + <ImageView + android:id="@android:id/icon" + android:layout_width="32dip" + android:layout_height="32dip" + android:layout_marginLeft="12dip" + android:cropToPadding="true" + android:background="#ccc" + android:scaleType="centerCrop"/> +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/recipient_selection_list_entry.xml b/OpenKeychain/src/main/res/layout/recipient_selection_list_entry.xml new file mode 100644 index 000000000..2be37fb4c --- /dev/null +++ b/OpenKeychain/src/main/res/layout/recipient_selection_list_entry.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dip" + android:orientation="horizontal" + android:gravity="center_vertical"> + <LinearLayout + android:layout_width="0dip" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="vertical" + android:layout_weight="1"> + <TextView android:id="@android:id/title" + android:textColor="?android:attr/textColorSecondary" + android:textSize="18sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="8dip" + android:singleLine="true" + android:ellipsize="end"/> + <TextView android:id="@android:id/text1" + android:textColor="?android:attr/textColorTertiary" + android:textSize="14sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="16dip" + android:singleLine="true" + android:ellipsize="end" + android:layout_marginTop="-4dip"/> + </LinearLayout> + <ImageView + android:id="@android:id/icon" + android:layout_width="48dip" + android:layout_height="48dip" + android:layout_marginLeft="12dip" + android:cropToPadding="true" + android:background="#ccc" + android:scaleType="centerCrop"/> +</LinearLayout>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/menu/encrypt_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_activity.xml new file mode 100644 index 000000000..c852fbb5c --- /dev/null +++ b/OpenKeychain/src/main/res/menu/encrypt_activity.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> + +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/check_use_symmetric" android:title="@string/label_symmetric" android:checkable="true"/> + <item android:id="@+id/check_use_armor" android:title="@string/label_ascii_armor" android:checkable="true" /> + <item android:id="@+id/check_delete_after_encrypt" android:title="@string/label_delete_after_encryption" android:checkable="true" /> +</menu>
\ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 6823c3c57..9284e63e3 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -113,6 +113,7 @@ <string name="label_algorithm">Algorithm</string> <string name="label_ascii_armor">ASCII Armor</string> <string name="label_select_public_keys">Recipients</string> + <string name="label_to">To</string> <string name="label_delete_after_encryption">Delete After Encryption</string> <string name="label_delete_after_decryption">Delete After Decryption</string> <string name="label_share_after_encryption">Share After Encryption</string> |