mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-24 01:32:16 -05:00
Refactor expiry dialog
This commit is contained in:
parent
e9fccff8bc
commit
369f6e080c
@ -20,19 +20,23 @@ package org.sufficientlysecure.keychain.service;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
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.
|
* to be done on a keyring.
|
||||||
*
|
* <p/>
|
||||||
* This class should include all types of operations supported in the backend.
|
* This class should include all types of operations supported in the backend.
|
||||||
*
|
* <p/>
|
||||||
* All changes are done in a differential manner. Besides the two key
|
* All changes are done in a differential manner. Besides the two key
|
||||||
* identification attributes, all attributes may be null, which indicates no
|
* identification attributes, all attributes may be null, which indicates no
|
||||||
* change to the keyring. This is also the reason why boxed values are used
|
* change to the keyring. This is also the reason why boxed values are used
|
||||||
* instead of primitives in the subclasses.
|
* instead of primitives in the subclasses.
|
||||||
*
|
* <p/>
|
||||||
* Application of operations in the backend should be fail-fast, which means an
|
* 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
|
* error in any included operation (for example revocation of a non-existent
|
||||||
* subkey) will cause the operation as a whole to fail.
|
* subkey) will cause the operation as a whole to fail.
|
||||||
@ -82,12 +86,23 @@ public class SaveKeyringParcel implements Parcelable {
|
|||||||
public int mKeysize;
|
public int mKeysize;
|
||||||
public int mFlags;
|
public int mFlags;
|
||||||
public Long mExpiry;
|
public Long mExpiry;
|
||||||
|
|
||||||
public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) {
|
public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) {
|
||||||
mAlgorithm = algorithm;
|
mAlgorithm = algorithm;
|
||||||
mKeysize = keysize;
|
mKeysize = keysize;
|
||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
mExpiry = expiry;
|
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 {
|
public static class SubkeyChange implements Serializable {
|
||||||
@ -95,11 +110,46 @@ public class SaveKeyringParcel implements Parcelable {
|
|||||||
public Integer mFlags;
|
public Integer mFlags;
|
||||||
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
|
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
|
||||||
public Long mExpiry;
|
public Long mExpiry;
|
||||||
|
|
||||||
|
public SubkeyChange(long keyId) {
|
||||||
|
mKeyId = keyId;
|
||||||
|
}
|
||||||
|
|
||||||
public SubkeyChange(long keyId, Integer flags, Long expiry) {
|
public SubkeyChange(long keyId, Integer flags, Long expiry) {
|
||||||
mKeyId = keyId;
|
mKeyId = keyId;
|
||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
mExpiry = expiry;
|
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) {
|
public SaveKeyringParcel(Parcel source) {
|
||||||
@ -121,7 +171,7 @@ public class SaveKeyringParcel implements Parcelable {
|
|||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel destination, int flags) {
|
public void writeToParcel(Parcel destination, int flags) {
|
||||||
destination.writeInt(mMasterKeyId == null ? 0 : 1);
|
destination.writeInt(mMasterKeyId == null ? 0 : 1);
|
||||||
if(mMasterKeyId != null) {
|
if (mMasterKeyId != null) {
|
||||||
destination.writeLong(mMasterKeyId);
|
destination.writeLong(mMasterKeyId);
|
||||||
}
|
}
|
||||||
destination.writeByteArray(mFingerprint);
|
destination.writeByteArray(mFingerprint);
|
||||||
@ -153,4 +203,16 @@ public class SaveKeyringParcel implements Parcelable {
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
|||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
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;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
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.adapter.UserIdsAddedAdapter;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.AddSubkeyDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment;
|
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.EditSubkeyDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class EditKeyFragment extends LoaderFragment implements
|
public class EditKeyFragment extends LoaderFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
@ -96,8 +93,8 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
private Uri mDataUri;
|
private Uri mDataUri;
|
||||||
|
|
||||||
private SaveKeyringParcel mSaveKeyringParcel;
|
private SaveKeyringParcel mSaveKeyringParcel;
|
||||||
private String mPrimaryUserId;
|
|
||||||
|
|
||||||
|
private String mPrimaryUserId;
|
||||||
private String mCurrentPassphrase;
|
private String mCurrentPassphrase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -399,23 +396,17 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
private void editSubkeyExpiry(final int position) {
|
private void editSubkeyExpiry(final int position) {
|
||||||
final long keyId = mSubkeysAdapter.getKeyId(position);
|
final long keyId = mSubkeysAdapter.getKeyId(position);
|
||||||
final Date creationDate = new Date(mSubkeysAdapter.getCreationDate(position));
|
final long creationDate = mSubkeysAdapter.getCreationDate(position);
|
||||||
final Date expiryDate = new Date(mSubkeysAdapter.getExpiryDate(position));
|
final long expiryDate = mSubkeysAdapter.getExpiryDate(position);
|
||||||
|
|
||||||
Handler returnHandler = new Handler() {
|
Handler returnHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE:
|
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE:
|
||||||
// SaveKeyringParcel.SubkeyChange subkeyChange = new SaveKeyringParcel.SubkeyChange();
|
long expiry = message.getData().getLong(EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY_DATE);
|
||||||
|
Log.d(Constants.TAG, "new expiry: " + expiry);
|
||||||
// mSaveKeyringParcel.mChangeSubKeys.add()
|
mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry = expiry;
|
||||||
// if (mSaveKeyringParcel.changePrimaryUserId != null
|
|
||||||
// && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) {
|
|
||||||
// mSaveKeyringParcel.changePrimaryUserId = null;
|
|
||||||
// } else {
|
|
||||||
// mSaveKeyringParcel.changePrimaryUserId = userId;
|
|
||||||
// }
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
||||||
@ -427,8 +418,8 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
ChangeExpiryDialogFragment dialogFragment =
|
EditSubkeyExpiryDialogFragment dialogFragment =
|
||||||
ChangeExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate);
|
EditSubkeyExpiryDialogFragment.newInstance(messenger, creationDate, expiryDate);
|
||||||
|
|
||||||
dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog");
|
dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog");
|
||||||
}
|
}
|
||||||
@ -501,9 +492,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void save(String passphrase) {
|
private void save(String passphrase) {
|
||||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mAddUserIds: " + mSaveKeyringParcel.mAddUserIds);
|
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
|
||||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mNewPassphrase: " + mSaveKeyringParcel.mNewPassphrase);
|
|
||||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mRevokeUserIds: " + mSaveKeyringParcel.mRevokeUserIds);
|
|
||||||
|
|
||||||
// Message is received after importing is done in KeychainIntentService
|
// Message is received after importing is done in KeychainIntentService
|
||||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||||
|
@ -161,6 +161,11 @@ public class SubkeysAdapter extends CursorAdapter {
|
|||||||
|
|
||||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
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
|
// for edit key
|
||||||
if (mSaveKeyringParcel != null) {
|
if (mSaveKeyringParcel != null) {
|
||||||
boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId));
|
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);
|
vEditImage.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
vEditImage.setVisibility(View.GONE);
|
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) {
|
if (isRevoked) {
|
||||||
vRevokedIcon.setVisibility(View.VISIBLE);
|
vRevokedIcon.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
@ -186,19 +211,6 @@ public class SubkeysAdapter extends CursorAdapter {
|
|||||||
vRevokedIcon.setVisibility(View.GONE);
|
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
|
// if key is expired or revoked, strike through text
|
||||||
boolean isInvalid = isRevoked || isExpired;
|
boolean isInvalid = isRevoked || isExpired;
|
||||||
if (isInvalid) {
|
if (isInvalid) {
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* 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.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
OpenKeychain/src/main/res/layout/expiry_dialog.xml
Normal file
16
OpenKeychain/src/main/res/layout/expiry_dialog.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/datePicker"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:spinnersShown="true"
|
||||||
|
android:calendarViewShown="false" />
|
||||||
|
<!-- Hide calendarView in tablets because of the unix warparound bug. -->
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -51,7 +51,7 @@
|
|||||||
<string name="btn_save">Save</string>
|
<string name="btn_save">Save</string>
|
||||||
<string name="btn_do_not_save">Cancel</string>
|
<string name="btn_do_not_save">Cancel</string>
|
||||||
<string name="btn_delete">Delete</string>
|
<string name="btn_delete">Delete</string>
|
||||||
<string name="btn_no_date">None</string>
|
<string name="btn_no_date">No Expiry</string>
|
||||||
<string name="btn_okay">Okay</string>
|
<string name="btn_okay">Okay</string>
|
||||||
<string name="btn_export_to_server">Upload To Keyserver</string>
|
<string name="btn_export_to_server">Upload To Keyserver</string>
|
||||||
<string name="btn_next">Next</string>
|
<string name="btn_next">Next</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user