From 369f6e080c110a0446aad793886e60924afe510e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 5 Aug 2014 15:07:11 +0200 Subject: [PATCH] Refactor expiry dialog --- .../keychain/service/SaveKeyringParcel.java | 72 ++++++- .../keychain/ui/EditKeyFragment.java | 33 +-- .../keychain/ui/adapter/SubkeysAdapter.java | 38 ++-- .../ui/dialog/ChangeExpiryDialogFragment.java | 187 ----------------- .../EditSubkeyExpiryDialogFragment.java | 189 ++++++++++++++++++ .../src/main/res/layout/expiry_dialog.xml | 16 ++ OpenKeychain/src/main/res/values/strings.xml | 2 +- 7 files changed, 309 insertions(+), 228 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java create mode 100644 OpenKeychain/src/main/res/layout/expiry_dialog.xml diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 3b55e6231..abc377b7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -20,19 +20,23 @@ package org.sufficientlysecure.keychain.service; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + import java.io.Serializable; import java.util.ArrayList; -/** This class is a a transferable representation for a collection of changes +/** + * This class is a a transferable representation for a collection of changes * to be done on a keyring. - * + *

* This class should include all types of operations supported in the backend. - * + *

* All changes are done in a differential manner. Besides the two key * identification attributes, all attributes may be null, which indicates no * change to the keyring. This is also the reason why boxed values are used * instead of primitives in the subclasses. - * + *

* Application of operations in the backend should be fail-fast, which means an * error in any included operation (for example revocation of a non-existent * subkey) will cause the operation as a whole to fail. @@ -82,12 +86,23 @@ public class SaveKeyringParcel implements Parcelable { public int mKeysize; public int mFlags; public Long mExpiry; + public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { mAlgorithm = algorithm; mKeysize = keysize; mFlags = flags; mExpiry = expiry; } + + @Override + public String toString() { + String out = "mAlgorithm: " + mAlgorithm + ", "; + out += "mKeysize: " + mKeysize + ", "; + out += "mFlags: " + mFlags; + out += "mExpiry: " + mExpiry; + + return out; + } } public static class SubkeyChange implements Serializable { @@ -95,11 +110,46 @@ public class SaveKeyringParcel implements Parcelable { public Integer mFlags; // this is a long unix timestamp, in seconds (NOT MILLISECONDS!) public Long mExpiry; + + public SubkeyChange(long keyId) { + mKeyId = keyId; + } + public SubkeyChange(long keyId, Integer flags, Long expiry) { mKeyId = keyId; mFlags = flags; mExpiry = expiry; } + + @Override + public String toString() { + String out = "mKeyId: " + mKeyId + ", "; + out += "mFlags: " + mFlags + ", "; + out += "mExpiry: " + mExpiry; + + return out; + } + } + + public SubkeyChange getSubkeyChange(long keyId) { + for (SubkeyChange subkeyChange : mChangeSubKeys) { + if (subkeyChange.mKeyId == keyId) { + return subkeyChange; + } + } + return null; + } + + public SubkeyChange getOrCreateSubkeyChange(long keyId) { + SubkeyChange foundSubkeyChange = getSubkeyChange(keyId); + if (foundSubkeyChange != null) { + return foundSubkeyChange; + } else { + // else, create a new one + SubkeyChange newSubkeyChange = new SubkeyChange(keyId); + mChangeSubKeys.add(newSubkeyChange); + return newSubkeyChange; + } } public SaveKeyringParcel(Parcel source) { @@ -121,7 +171,7 @@ public class SaveKeyringParcel implements Parcelable { @Override public void writeToParcel(Parcel destination, int flags) { destination.writeInt(mMasterKeyId == null ? 0 : 1); - if(mMasterKeyId != null) { + if (mMasterKeyId != null) { destination.writeLong(mMasterKeyId); } destination.writeByteArray(mFingerprint); @@ -153,4 +203,16 @@ public class SaveKeyringParcel implements Parcelable { return 0; } + @Override + public String toString() { + String out = "mMasterKeyId: " + mMasterKeyId + "\n"; + out += "mNewPassphrase: " + mNewPassphrase + "\n"; + out += "mAddSubKeys: " + mAddSubKeys + "\n"; + out += "mChangeSubKeys: " + mChangeSubKeys + "\n"; + out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n"; + out += "mRevokeUserIds: " + mRevokeUserIds + "\n"; + out += "mRevokeSubKeys: " + mRevokeSubKeys; + + return out; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 7460b73b4..6b062af59 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -45,7 +45,6 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper; import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -60,15 +59,13 @@ import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.ChangeExpiryDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; -import java.util.Date; - public class EditKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { @@ -96,8 +93,8 @@ public class EditKeyFragment extends LoaderFragment implements private Uri mDataUri; private SaveKeyringParcel mSaveKeyringParcel; - private String mPrimaryUserId; + private String mPrimaryUserId; private String mCurrentPassphrase; /** @@ -399,23 +396,17 @@ public class EditKeyFragment extends LoaderFragment implements private void editSubkeyExpiry(final int position) { final long keyId = mSubkeysAdapter.getKeyId(position); - final Date creationDate = new Date(mSubkeysAdapter.getCreationDate(position)); - final Date expiryDate = new Date(mSubkeysAdapter.getExpiryDate(position)); + final long creationDate = mSubkeysAdapter.getCreationDate(position); + final long expiryDate = mSubkeysAdapter.getExpiryDate(position); Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { - case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: -// SaveKeyringParcel.SubkeyChange subkeyChange = new SaveKeyringParcel.SubkeyChange(); - -// mSaveKeyringParcel.mChangeSubKeys.add() -// if (mSaveKeyringParcel.changePrimaryUserId != null -// && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) { -// mSaveKeyringParcel.changePrimaryUserId = null; -// } else { -// mSaveKeyringParcel.changePrimaryUserId = userId; -// } + case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE: + long expiry = message.getData().getLong(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE); + Log.d(Constants.TAG, "new expiry: " + expiry); + mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry; break; } getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad(); @@ -427,8 +418,8 @@ public class EditKeyFragment extends LoaderFragment implements DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { public void run() { - ChangeExpiryDialogFragment dialogFragment = - ChangeExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); + EditSubkeyExpiryDialogFragment dialogFragment = + EditSubkeyExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate); dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog"); } @@ -501,9 +492,7 @@ public class EditKeyFragment extends LoaderFragment implements } private void save(String passphrase) { - Log.d(Constants.TAG, "mSaveKeyringParcel.mAddUserIds: " + mSaveKeyringParcel.mAddUserIds); - Log.d(Constants.TAG, "mSaveKeyringParcel.mNewPassphrase: " + mSaveKeyringParcel.mNewPassphrase); - Log.d(Constants.TAG, "mSaveKeyringParcel.mRevokeUserIds: " + mSaveKeyringParcel.mRevokeUserIds); + Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString()); // Message is received after importing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 25b3c0fc5..dd972866c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -161,6 +161,11 @@ public class SubkeysAdapter extends CursorAdapter { boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; + Date expiryDate = null; + if (!cursor.isNull(INDEX_EXPIRY)) { + expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); + } + // for edit key if (mSaveKeyringParcel != null) { boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)); @@ -171,11 +176,31 @@ public class SubkeysAdapter extends CursorAdapter { } } + SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId); + if (subkeyChange != null) { + // 0 is "no expiry" + if (subkeyChange.mExpiry != null && subkeyChange.mExpiry != 0) { + expiryDate = new Date(subkeyChange.mExpiry * 1000); + } + } + vEditImage.setVisibility(View.VISIBLE); } else { vEditImage.setVisibility(View.GONE); } + boolean isExpired; + if (expiryDate != null) { + isExpired = expiryDate.before(new Date()); + + vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + + DateFormat.getDateFormat(context).format(expiryDate)); + } else { + isExpired = false; + + vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none)); + } + if (isRevoked) { vRevokedIcon.setVisibility(View.VISIBLE); } else { @@ -186,19 +211,6 @@ public class SubkeysAdapter extends CursorAdapter { vRevokedIcon.setVisibility(View.GONE); } - boolean isExpired; - if (!cursor.isNull(INDEX_EXPIRY)) { - Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); - isExpired = expiryDate.before(new Date()); - - vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " - + DateFormat.getDateFormat(context).format(expiryDate)); - } else { - isExpired = false; - - vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none)); - } - // if key is expired or revoked, strike through text boolean isInvalid = isRevoked || isExpired; if (isInvalid) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java deleted file mode 100644 index d5354a9f6..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ChangeExpiryDialogFragment.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.dialog; - -import android.app.DatePickerDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.DialogFragment; -import android.text.format.DateUtils; -import android.widget.DatePicker; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -public class ChangeExpiryDialogFragment extends DialogFragment { - private static final String ARG_MESSENGER = "messenger"; - private static final String ARG_CREATION_DATE = "creation_date"; - private static final String ARG_EXPIRY_DATE = "expiry_date"; - - public static final int MESSAGE_NEW_EXPIRY_DATE = 1; - public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; - - private Messenger mMessenger; - private Calendar mCreationCal; - private Calendar mExpiryCal; - - private int mDatePickerResultCount = 0; - private DatePickerDialog.OnDateSetListener mExpiryDateSetListener = - new DatePickerDialog.OnDateSetListener() { - public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - selectedCal.set(year, monthOfYear, dayOfMonth); - if (mExpiryCal != null) { - long numDays = (selectedCal.getTimeInMillis() / 86400000) - - (mExpiryCal.getTimeInMillis() / 86400000); - if (numDays > 0) { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } else { - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime()); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } - } - }; - - public class ExpiryDatePickerDialog extends DatePickerDialog { - - public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack, - int year, int monthOfYear, int dayOfMonth) { - super(context, callBack, year, monthOfYear, dayOfMonth); - } - - // set permanent title - public void setTitle(CharSequence title) { - super.setTitle(getContext().getString(R.string.expiry_date_dialog_title)); - } - } - - /** - * Creates new instance of this dialog fragment - */ - public static ChangeExpiryDialogFragment newInstance(Messenger messenger, - Date creationDate, Date expiryDate) { - ChangeExpiryDialogFragment frag = new ChangeExpiryDialogFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_MESSENGER, messenger); - args.putSerializable(ARG_CREATION_DATE, creationDate); - args.putSerializable(ARG_EXPIRY_DATE, expiryDate); - - frag.setArguments(args); - - return frag; - } - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - mMessenger = getArguments().getParcelable(ARG_MESSENGER); - Date creationDate = (Date) getArguments().getSerializable(ARG_CREATION_DATE); - Date expiryDate = (Date) getArguments().getSerializable(ARG_EXPIRY_DATE); - - mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mCreationCal.setTime(creationDate); - mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - mExpiryCal.setTime(expiryDate); - - /* - * Using custom DatePickerDialog which overrides the setTitle because - * the DatePickerDialog title is buggy (unix warparound bug). - * See: https://code.google.com/p/android/issues/detail?id=49066 - */ - DatePickerDialog dialog = new ExpiryDatePickerDialog(getActivity(), - mExpiryDateSetListener, mExpiryCal.get(Calendar.YEAR), mExpiryCal.get(Calendar.MONTH), - mExpiryCal.get(Calendar.DAY_OF_MONTH)); - mDatePickerResultCount = 0; - dialog.setCancelable(true); - dialog.setButton(Dialog.BUTTON_NEGATIVE, - getActivity().getString(R.string.btn_no_date), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - // Note: Ignore results after the first one - android sends multiples. - if (mDatePickerResultCount++ == 0) { - // none expiry dates corresponds to a null message - Bundle data = new Bundle(); - data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null); - sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); - } - } - } - ); - - // setCalendarViewShown() is supported from API 11 onwards. - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // Hide calendarView in tablets because of the unix warparound bug. - dialog.getDatePicker().setCalendarViewShown(false); - } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - // will crash with IllegalArgumentException if we set a min date - // that is not before expiry - if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { - dialog.getDatePicker().setMinDate(mCreationCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } else { - // When created date isn't available - dialog.getDatePicker().setMinDate(mExpiryCal.getTime().getTime() - + DateUtils.DAY_IN_MILLIS); - } - } - - return dialog; - } - - /** - * Send message back to handler which is initialized in a activity - * - * @param what Message integer you want to send - */ - private void sendMessageToHandler(Integer what, Bundle data) { - Message msg = Message.obtain(); - msg.what = what; - if (data != null) { - msg.setData(data); - } - - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java new file mode 100644 index 000000000..1712b922f --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.v4.app.DialogFragment; +import android.text.format.DateUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.DatePicker; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +public class EditSubkeyExpiryDialogFragment extends DialogFragment { + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_CREATION_DATE = "creation_date"; + private static final String ARG_EXPIRY_DATE = "expiry_date"; + + public static final int MESSAGE_NEW_EXPIRY_DATE = 1; + public static final int MESSAGE_CANCEL = 2; + public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date"; + + private Messenger mMessenger; + private Calendar mCreationCal; + private Calendar mExpiryCal; + + private DatePicker mDatePicker; + + /** + * Creates new instance of this dialog fragment + */ + public static EditSubkeyExpiryDialogFragment newInstance(Messenger messenger, + long creationDate, long expiryDate) { + EditSubkeyExpiryDialogFragment frag = new EditSubkeyExpiryDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_MESSENGER, messenger); + args.putLong(ARG_CREATION_DATE, creationDate); + args.putLong(ARG_EXPIRY_DATE, expiryDate); + + frag.setArguments(args); + + return frag; + } + + /** + * Creates dialog + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + mMessenger = getArguments().getParcelable(ARG_MESSENGER); + Date creationDate = new Date(getArguments().getLong(ARG_CREATION_DATE) * 1000); + Date expiryDate = new Date(getArguments().getLong(ARG_EXPIRY_DATE) * 1000); + + mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + mCreationCal.setTime(creationDate); + mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + mExpiryCal.setTime(expiryDate); + + Log.d(Constants.TAG, "onCreateDialog"); + + // Explicitly not using DatePickerDialog here! + // DatePickerDialog is difficult to customize and has many problems (see old git versions) + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); + + alert.setTitle(R.string.expiry_date_dialog_title); + + LayoutInflater inflater = activity.getLayoutInflater(); + View view = inflater.inflate(R.layout.expiry_dialog, null); + alert.setView(view); + + mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { + // will crash with IllegalArgumentException if we set a min date + // that is not before expiry + if (mCreationCal != null && mCreationCal.before(mExpiryCal)) { + mDatePicker.setMinDate(mCreationCal.getTime().getTime() + + DateUtils.DAY_IN_MILLIS); + } else { + // When created date isn't available + mDatePicker.setMinDate(mExpiryCal.getTime().getTime() + + DateUtils.DAY_IN_MILLIS); + } + } + + alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + + Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + //noinspection ResourceType + selectedCal.set(mDatePicker.getYear(), mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); + + if (mExpiryCal != null) { + long numDays = (selectedCal.getTimeInMillis() / 86400000) + - (mExpiryCal.getTimeInMillis() / 86400000); + if (numDays > 0) { + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + } else { + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime().getTime() / 1000); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + } + }); + + alert.setNeutralButton(R.string.btn_no_date, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + + // "no expiry" corresponds to a 0 + Bundle data = new Bundle(); + data.putLong(MESSAGE_DATA_EXPIRY_DATE, 0); + sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data); + } + }); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dismiss(); + } + }); + + return alert.show(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + dismiss(); + sendMessageToHandler(MESSAGE_CANCEL, null); + } + + /** + * Send message back to handler which is initialized in a activity + * + * @param what Message integer you want to send + */ + private void sendMessageToHandler(Integer what, Bundle data) { + Message msg = Message.obtain(); + msg.what = what; + if (data != null) { + msg.setData(data); + } + + try { + mMessenger.send(msg); + } catch (RemoteException e) { + Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); + } catch (NullPointerException e) { + Log.w(Constants.TAG, "Messenger is null!", e); + } + } +} diff --git a/OpenKeychain/src/main/res/layout/expiry_dialog.xml b/OpenKeychain/src/main/res/layout/expiry_dialog.xml new file mode 100644 index 000000000..14fff0b3f --- /dev/null +++ b/OpenKeychain/src/main/res/layout/expiry_dialog.xml @@ -0,0 +1,16 @@ + + + + + + + \ 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 ed5dca813..18031e25b 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -51,7 +51,7 @@ Save Cancel Delete - None + No Expiry Okay Upload To Keyserver Next