aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-06-01 03:23:51 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-06-01 03:23:51 +0200
commitcee1a8c7531904b55d13bda972b79e8b7c7ed67c (patch)
treec81bb97d3f11337387e42b4eec8227fd56b032c8 /OpenKeychain
parentdbfa55f6b963ff8c5a975c45a2805838eb1781f7 (diff)
downloadopen-keychain-cee1a8c7531904b55d13bda972b79e8b7c7ed67c.tar.gz
open-keychain-cee1a8c7531904b55d13bda972b79e8b7c7ed67c.tar.bz2
open-keychain-cee1a8c7531904b55d13bda972b79e8b7c7ed67c.zip
multi-decrypt: first steps, split up DecryptFilesFragment
Diffstat (limited to 'OpenKeychain')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesInputFragment.java136
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java398
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_files_input_fragment.xml192
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_files_list_fragment.xml51
5 files changed, 549 insertions, 247 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
index 81fb6a392..f08ee5d3d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
@@ -21,15 +21,15 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
-import org.sufficientlysecure.keychain.util.Log;
+
public class DecryptFilesActivity extends BaseActivity {
@@ -94,13 +94,24 @@ public class DecryptFilesActivity extends BaseActivity {
}
boolean showOpenDialog = ACTION_DECRYPT_DATA_OPEN.equals(action);
- DecryptFilesFragment frag = DecryptFilesFragment.newInstance(uri, showOpenDialog);
+ DecryptFilesInputFragment frag = DecryptFilesInputFragment.newInstance(uri, showOpenDialog);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
getSupportFragmentManager().beginTransaction()
.replace(R.id.decrypt_files_fragment_container, frag)
- .commitAllowingStateLoss();
+ .commit();
+
+ }
+
+ public void displayListFragment(Uri inputUri, DecryptVerifyResult result) {
+
+ DecryptFilesListFragment frag = DecryptFilesListFragment.newInstance(inputUri, result);
+
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.decrypt_files_fragment_container, frag)
+ .addToBackStack("list")
+ .commit();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesInputFragment.java
index 3f15376cb..25494e0d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesInputFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesInputFragment.java
@@ -26,11 +26,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CheckBox;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
@@ -40,35 +38,26 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
-import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.Log;
-import java.io.File;
-
-public class DecryptFilesInputFragment extends DecryptFragment {
+public class DecryptFilesInputFragment extends CryptoOperationFragment {
public static final String ARG_URI = "uri";
public static final String ARG_OPEN_DIRECTLY = "open_directly";
private static final int REQUEST_CODE_INPUT = 0x00007003;
- private static final int REQUEST_CODE_OUTPUT = 0x00007007;
// view
private TextView mFilename;
- private CheckBox mDeleteAfter;
private View mDecryptButton;
// model
private Uri mInputUri = null;
private Uri mOutputUri = null;
- private String mCurrentCryptoOperation;
-
- /**
- * Creates new instance of this fragment
- */
public static DecryptFilesInputFragment newInstance(Uri uri, boolean openDirectly) {
DecryptFilesInputFragment frag = new DecryptFilesInputFragment();
@@ -81,15 +70,14 @@ public class DecryptFilesInputFragment extends DecryptFragment {
return frag;
}
- /**
- * Inflate the layout for this fragment
- */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.decrypt_files_fragment, container, false);
+ View view = inflater.inflate(R.layout.decrypt_files_input_fragment, container, false);
+
+ // hide result view for this fragment
+ getActivity().findViewById(R.id.result_main_layout).setVisibility(View.GONE);
mFilename = (TextView) view.findViewById(R.id.decrypt_files_filename);
- mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_files_delete_after_decryption);
mDecryptButton = view.findViewById(R.id.decrypt_files_action_decrypt);
view.findViewById(R.id.decrypt_files_browse).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -152,45 +140,6 @@ public class DecryptFilesInputFragment extends DecryptFragment {
return;
}
- startDecryptFilenames();
- }
-
- private String removeEncryptedAppend(String name) {
- if (name.endsWith(Constants.FILE_EXTENSION_ASC)
- || name.endsWith(Constants.FILE_EXTENSION_PGP_MAIN)
- || name.endsWith(Constants.FILE_EXTENSION_PGP_ALTERNATE)) {
- return name.substring(0, name.length() - 4);
- }
- return name;
- }
-
- private void askForOutputFilename(String originalFilename) {
- if (TextUtils.isEmpty(originalFilename)) {
- originalFilename = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri));
- }
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- File file = new File(mInputUri.getPath());
- File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- File targetFile = new File(parentDir, originalFilename);
- FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
- getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
- } else {
- FileHelper.saveDocument(this, "*/*", originalFilename, REQUEST_CODE_OUTPUT);
- }
- }
-
- private void displayMetadata(DecryptVerifyResult result) {
-
- }
-
- private void startDecrypt() {
- mCurrentCryptoOperation = KeychainIntentService.ACTION_DECRYPT_VERIFY;
- cryptoOperation(new CryptoInputParcel());
- }
-
- private void startDecryptFilenames() {
- mCurrentCryptoOperation = KeychainIntentService.ACTION_DECRYPT_METADATA;
cryptoOperation(new CryptoInputParcel());
}
@@ -203,7 +152,7 @@ public class DecryptFilesInputFragment extends DecryptFragment {
// fill values for this action
Bundle data = new Bundle();
// use current operation, either decrypt metadata or decrypt payload
- intent.setAction(mCurrentCryptoOperation);
+ intent.setAction(KeychainIntentService.ACTION_DECRYPT_METADATA);
// data
@@ -240,41 +189,18 @@ public class DecryptFilesInputFragment extends DecryptFragment {
DecryptVerifyResult result =
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
+ DecryptFilesActivity activity = ((DecryptFilesActivity) getActivity());
+ if (activity == null) {
+ // nothing we can do
+ return;
+ }
+
if (result.success()) {
- switch (mCurrentCryptoOperation) {
- case KeychainIntentService.ACTION_DECRYPT_METADATA: {
- displayMetadata(result);
- // askForOutputFilename(pgpResult.getDecryptMetadata().getFilename());
- break;
- }
- case KeychainIntentService.ACTION_DECRYPT_VERIFY: {
- // display signature result in activity
- loadVerifyResult(result);
-
- if (mDeleteAfter.isChecked()) {
- // Create and show dialog to delete original file
- DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri);
- deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog");
- setInputUri(null);
- }
-
- /*
- // A future open after decryption feature
- if () {
- Intent viewFile = new Intent(Intent.ACTION_VIEW);
- viewFile.setInputData(mOutputUri);
- startActivity(viewFile);
- }
- */
- break;
- }
- default: {
- Log.e(Constants.TAG, "Bug: not supported operation!");
- break;
- }
- }
+ activity.displayListFragment(mInputUri, result);
+ return;
}
- result.createNotify(getActivity()).show(DecryptFilesInputFragment.this);
+ result.createNotify(activity).show(DecryptFilesInputFragment.this);
+
}
}
@@ -293,31 +219,13 @@ public class DecryptFilesInputFragment extends DecryptFragment {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_INPUT: {
- if (resultCode == Activity.RESULT_OK && data != null) {
- setInputUri(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();
- startDecrypt();
- }
- return;
- }
+ if (requestCode != REQUEST_CODE_INPUT) {
+ return;
+ }
- default: {
- super.onActivityResult(requestCode, resultCode, data);
- }
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ setInputUri(data.getData());
}
}
- @Override
- protected void onVerifyLoaded(boolean hideErrorOverlay) {
-
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java
new file mode 100644
index 000000000..e86275b5d
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java
@@ -0,0 +1,398 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.openintents.openpgp.OpenPgpMetadata;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.DecryptFilesListFragment.DecryptFilesAdapter.ViewModel;
+import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration;
+import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
+import org.sufficientlysecure.keychain.util.FileHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+
+public class DecryptFilesListFragment extends DecryptFragment {
+ public static final String ARG_URI = "uri";
+
+ private static final int REQUEST_CODE_OUTPUT = 0x00007007;
+
+ private Uri mInputUri = null;
+ private DecryptVerifyResult mResult;
+
+ private Uri mOutputUri = null;
+ private RecyclerView mFilesList;
+ private DecryptFilesAdapter mAdapter;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static DecryptFilesListFragment newInstance(Uri uri, DecryptVerifyResult result) {
+ DecryptFilesListFragment frag = new DecryptFilesListFragment();
+
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_URI, uri);
+ args.putParcelable(ARG_DECRYPT_VERIFY_RESULT, result);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * Inflate the layout for this fragment
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.decrypt_files_list_fragment, container, false);
+
+ mFilesList = (RecyclerView) view.findViewById(R.id.decrypted_files_list);
+
+ mFilesList.addItemDecoration(new SpacesItemDecoration(
+ FormattingUtils.dpToPx(getActivity(), 4)));
+ // mFilesList.setHasFixedSize(true);
+ mFilesList.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mFilesList.setItemAnimator(new DefaultItemAnimator());
+
+ mAdapter = new DecryptFilesAdapter(getActivity(), new ArrayList<ViewModel>());
+ mFilesList.setAdapter(mAdapter);
+
+ return view;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putParcelable(ARG_URI, mInputUri);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Bundle state = getArguments();
+ mInputUri = state.getParcelable(ARG_URI);
+
+ if (savedInstanceState == null) {
+ displayMetadata(state.<DecryptVerifyResult>getParcelable(ARG_DECRYPT_VERIFY_RESULT));
+ }
+
+ }
+
+ private String removeEncryptedAppend(String name) {
+ if (name.endsWith(Constants.FILE_EXTENSION_ASC)
+ || name.endsWith(Constants.FILE_EXTENSION_PGP_MAIN)
+ || name.endsWith(Constants.FILE_EXTENSION_PGP_ALTERNATE)) {
+ return name.substring(0, name.length() - 4);
+ }
+ return name;
+ }
+
+ private void askForOutputFilename(String originalFilename) {
+ if (TextUtils.isEmpty(originalFilename)) {
+ originalFilename = removeEncryptedAppend(FileHelper.getFilename(getActivity(), mInputUri));
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ File file = new File(mInputUri.getPath());
+ File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
+ File targetFile = new File(parentDir, originalFilename);
+ FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
+ getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
+ } else {
+ FileHelper.saveDocument(this, "*/*", originalFilename, REQUEST_CODE_OUTPUT);
+ }
+ }
+
+ private void displayMetadata(DecryptVerifyResult result) {
+ loadVerifyResult(result);
+
+ OpenPgpMetadata metadata = result.getDecryptMetadata();
+ mAdapter.add(metadata);
+ mFilesList.requestFocus();
+
+ }
+
+ @Override
+ @SuppressLint("HandlerLeak")
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
+ // Send all information needed to service to decrypt in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+ // use current operation, either decrypt metadata or decrypt payload
+ intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY);
+
+ // data
+
+ Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
+
+ PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mInputUri, mOutputUri)
+ .setAllowSymmetricDecryption(true);
+
+ data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input);
+ data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput);
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after decrypting is done in KeychainIntentService
+ ServiceProgressHandler saveHandler = new ServiceProgressHandler(
+ getActivity(),
+ getString(R.string.progress_decrypting),
+ ProgressDialog.STYLE_HORIZONTAL,
+ ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
+ @Override
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ // handle pending messages
+ if (handlePendingMessage(message)) {
+ return;
+ }
+
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ DecryptVerifyResult result =
+ returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
+
+ if (result.success()) {
+ // display signature result in activity
+ loadVerifyResult(result);
+
+ /*
+ // A future open after decryption feature
+ if () {
+ Intent viewFile = new Intent(Intent.ACTION_VIEW);
+ viewFile.setInputData(mOutputUri);
+ startActivity(viewFile);
+ }
+ */
+ }
+ result.createNotify(getActivity()).show(DecryptFilesListFragment.this);
+ }
+
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ saveHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ 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();
+ // startDecrypt();
+ }
+ return;
+ }
+
+ default: {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+ }
+
+ @Override
+ protected void onVerifyLoaded(boolean hideErrorOverlay) {
+
+ }
+
+ public static class DecryptFilesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private Context mContext;
+ private List<ViewModel> mDataset;
+
+ public static class ViewModel {
+ OpenPgpMetadata mMetadata;
+ Bitmap thumbnail;
+
+ ViewModel(Context context, OpenPgpMetadata metadata) {
+ mMetadata = metadata;
+ int px = FormattingUtils.dpToPx(context, 48);
+ // this.thumbnail = FileHelper.getThumbnail(context, inputUri, new Point(px, px));
+ }
+
+ // Depends on inputUri only
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ViewModel viewModel = (ViewModel) o;
+ return !(mMetadata != null ? !mMetadata.equals(viewModel.mMetadata)
+ : viewModel.mMetadata != null);
+ }
+
+ // Depends on inputUri only
+ @Override
+ public int hashCode() {
+ return mMetadata != null ? mMetadata.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return mMetadata.toString();
+ }
+ }
+
+ // Provide a reference to the views for each data item
+ // Complex data items may need more than one view per item, and
+ // you provide access to all the views for a data item in a view holder
+ class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView filename;
+ public TextView fileSize;
+ public View removeButton;
+ public ImageView thumbnail;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ filename = (TextView) itemView.findViewById(R.id.filename);
+ fileSize = (TextView) itemView.findViewById(R.id.filesize);
+ removeButton = itemView.findViewById(R.id.action_remove_file_from_list);
+ thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
+ }
+ }
+
+ // Provide a suitable constructor (depends on the kind of dataset)
+ public DecryptFilesAdapter(Context context, List<ViewModel> myDataset) {
+ mContext = context;
+ mDataset = myDataset;
+ }
+
+ // Create new views (invoked by the layout manager)
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ //inflate your layout and pass it to view holder
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.file_list_entry, parent, false);
+ return new ViewHolder(v);
+ }
+
+ // Replace the contents of a view (invoked by the layout manager)
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
+ ViewHolder thisHolder = (ViewHolder) holder;
+ // - get element from your dataset at this position
+ // - replace the contents of the view with that element
+ final ViewModel model = mDataset.get(position);
+
+ thisHolder.filename.setText(model.mMetadata.getFilename());
+
+ long size = model.mMetadata.getOriginalSize();
+ if (size == -1) {
+ thisHolder.fileSize.setText("");
+ } else {
+ thisHolder.fileSize.setText(FileHelper.readableFileSize(size));
+ }
+ thisHolder.removeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ remove(model);
+ }
+ });
+
+ if (model.thumbnail != null) {
+ thisHolder.thumbnail.setImageBitmap(model.thumbnail);
+ } else {
+ thisHolder.thumbnail.setImageResource(R.drawable.ic_doc_generic_am);
+ }
+ }
+
+ // Return the size of your dataset (invoked by the layout manager)
+ @Override
+ public int getItemCount() {
+ return mDataset.size();
+ }
+
+ public void add(OpenPgpMetadata metadata) {
+ ViewModel newModel = new ViewModel(mContext, metadata);
+ mDataset.add(newModel);
+ notifyItemInserted(mDataset.size());
+ }
+
+ public void addAll(ArrayList<OpenPgpMetadata> metadatas) {
+ if (metadatas != null) {
+ int startIndex = mDataset.size();
+ for (OpenPgpMetadata metadata : metadatas) {
+ ViewModel newModel = new ViewModel(mContext, metadata);
+ if (mDataset.contains(newModel)) {
+ Log.e(Constants.TAG, "Skipped duplicate " + metadata);
+ } else {
+ mDataset.add(newModel);
+ }
+ }
+ notifyItemRangeInserted(startIndex, mDataset.size() - startIndex);
+ }
+ }
+
+ public void remove(ViewModel model) {
+ int position = mDataset.indexOf(model);
+ mDataset.remove(position);
+ notifyItemRemoved(position);
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/res/layout/decrypt_files_input_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_files_input_fragment.xml
index 22ee7e09f..b7e70ce10 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_files_input_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_files_input_fragment.xml
@@ -2,148 +2,82 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingTop="4dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
android:orientation="vertical">
- <LinearLayout
+ <View
+ android:id="@+id/status_divider"
+ android:layout_height="1dip"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <ScrollView
- android:fillViewport="true"
- android:paddingTop="8dp"
- android:layout_width="match_parent"
- android:scrollbars="vertical"
- android:layout_height="0dp"
- android:layout_weight="1">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <View
- android:id="@+id/status_divider"
- android:layout_height="1dip"
- android:layout_width="match_parent"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingTop="4dp"
- 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/decrypt_files_browse"
- android:clickable="true"
- android:background="?android:selectableItemBackground">
+ android:background="?android:attr/listDivider" />
- <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/decrypt_files_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_folder_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical" />
- </LinearLayout>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider"
- android:layout_marginBottom="8dp" />
-
- <CheckBox
- android:id="@+id/decrypt_files_delete_after_decryption"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/label_delete_after_decryption" />
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
+ android:id="@+id/decrypt_files_browse"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground">
- <TextView
- android:id="@+id/decrypt_files_action_decrypt"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:text="@string/btn_decrypt_verify_file"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
- android:drawableRight="@drawable/ic_save_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/label_file_colon"
+ android:gravity="center_vertical" />
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider"
- android:layout_above="@+id/decrypt_files_action_decrypt" />
+ <TextView
+ android:id="@+id/decrypt_files_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_folder_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical" />
- </RelativeLayout>
- </LinearLayout>
- </LinearLayout>
- </ScrollView>
</LinearLayout>
- <!-- TODO: Use this layout later to hide file list -->
- <LinearLayout
- android:visibility="gone"
- android:id="@+id/decrypt_content"
+ <View
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"></LinearLayout>
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider"
+ android:layout_marginBottom="8dp" />
- <LinearLayout
- android:visibility="gone"
- android:id="@+id/decrypt_error_overlay"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical">
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@+id/decrypt_files_action_decrypt"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/decrypt_invalid_text"
- android:padding="16dp"
- android:layout_gravity="center"
- android:textColor="@color/android_red_light" />
-
- <Button
- android:id="@+id/decrypt_error_overlay_button"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/button_edgy"
- android:textColor="@color/android_red_light"
- android:text="@string/decrypt_invalid_button"
- android:layout_gravity="center_horizontal" />
- </LinearLayout>
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:text="@string/btn_decrypt_verify_file"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ android:drawableRight="@drawable/ic_save_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider"
+ android:layout_above="@+id/decrypt_files_action_decrypt" />
+
+ </RelativeLayout>
+
</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/decrypt_files_list_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_files_list_fragment.xml
new file mode 100644
index 000000000..75e97f867
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/decrypt_files_list_fragment.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/decrypt_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/decrypted_files_list"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:scrollbars="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:visibility="gone"
+ android:id="@+id/decrypt_error_overlay"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center_vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/decrypt_invalid_text"
+ android:padding="16dp"
+ android:layout_gravity="center"
+ android:textColor="@color/android_red_light" />
+
+ <Button
+ android:id="@+id/decrypt_error_overlay_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/button_edgy"
+ android:textColor="@color/android_red_light"
+ android:text="@string/decrypt_invalid_button"
+ android:layout_gravity="center_horizontal" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file