rearrange linked id layouts, add CertListWidget

This commit is contained in:
Vincent Breitmoser 2015-03-09 21:04:03 +01:00
parent 159b197930
commit ebf3596341
6 changed files with 295 additions and 80 deletions

View File

@ -20,6 +20,7 @@ dependencies {
compile 'it.neokree:MaterialNavigationDrawer:1.3.1'
compile 'com.nispok:snackbar:2.9.1'
compile 'com.getbase:floatingactionbutton:1.8.0'
compile 'com.ocpsoft:ocpsoft-pretty-time:1.0.6'
// libs as submodules
compile project(':extern:openpgp-api-lib')

View File

@ -839,9 +839,7 @@ public class ViewKeyActivity extends BaseActivity implements
mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
if (oldFingerprint == null) {
startFragment(mIsSecret, fpData);
}
startFragment(mIsSecret, fpData);
// get name, email, and comment from USER_ID
String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
@ -1000,21 +998,25 @@ public class ViewKeyActivity extends BaseActivity implements
}
private void startFragment(boolean isSecret, byte[] fingerprint) {
// Create an instance of the fragment
final ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri, isSecret, fingerprint);
private void startFragment(final boolean isSecret, final byte[] fingerprint) {
new Handler().post(new Runnable() {
@Override
public void run() {
FragmentManager manager = getSupportFragmentManager();
manager.popBackStack("linked_id", FragmentManager.POP_BACK_STACK_INCLUSIVE);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
manager.beginTransaction()
.replace(R.id.view_key_fragment, frag, "main")
.commit();
if (manager.getBackStackEntryCount() == 0) {
// Create an instance of the fragment
final ViewKeyFragment frag = ViewKeyFragment.newInstance(
mDataUri, isSecret, fingerprint);
manager.beginTransaction()
.replace(R.id.view_key_fragment, frag)
.commit();
manager.popBackStack();
} else {
// not sure yet if we actually want this!
// manager.popBackStack();
}
}
});
}

View File

@ -22,7 +22,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ViewAnimator;
@ -44,10 +43,10 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsCertAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.widget.CertListWidget;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.util.Log;
@ -61,8 +60,7 @@ public class LinkedIdViewFragment extends Fragment implements
private static final String ARG_LID_RANK = "rank";
private static final String ARG_SHOWCERT = "verified";
private static final String ARG_FINGERPRINT = "fingerprint";
private static final int LOADER_ID_LINKED_CERTS = 1;
private static final int LOADER_ID_LINKED_ID = 2;
private static final int LOADER_ID_LINKED_ID = 1;
private RawLinkedIdentity mLinkedId;
private LinkedCookieResource mLinkedResource;
@ -74,10 +72,8 @@ public class LinkedIdViewFragment extends Fragment implements
private boolean mInProgress;
private LinkedIdsCertAdapter mCertAdapter;
private Uri mDataUri;
private ViewHolder mViewHolder;
private View mCurrentCert;
private int mLidRank;
private OnIdentityLoadedListener mIdLoadedListener;
@ -109,11 +105,9 @@ public class LinkedIdViewFragment extends Fragment implements
mContext = getActivity();
mInflater = getLayoutInflater(savedInstanceState);
mCertAdapter = new LinkedIdsCertAdapter(getActivity(), null, 0);
// getLoaderManager().initLoader(LOADER_ID_LINKED_CERTS, null, this);
getLoaderManager().initLoader(LOADER_ID_LINKED_ID, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
@ -122,10 +116,6 @@ public class LinkedIdViewFragment extends Fragment implements
UserIdsAdapter.USER_PACKETS_PROJECTION,
Tables.USER_PACKETS + "." + UserPackets.RANK
+ " = " + Integer.toString(mLidRank), null, null);
case LOADER_ID_LINKED_CERTS:
return LinkedIdsCertAdapter.createLoader(getActivity(), mDataUri);
default:
return null;
}
@ -162,10 +152,6 @@ public class LinkedIdViewFragment extends Fragment implements
}
break;
case LOADER_ID_LINKED_CERTS:
mCertAdapter.swapCursor(cursor);
break;
}
}
@ -180,6 +166,16 @@ public class LinkedIdViewFragment extends Fragment implements
private void loadIdentity(RawLinkedIdentity linkedId, int certStatus) {
mLinkedId = linkedId;
mViewHolder.setShowVerifying(false);
{
Bundle args = new Bundle();
args.putParcelable(CertListWidget.ARG_URI, mDataUri);
args.putInt(CertListWidget.ARG_RANK, mLidRank);
getLoaderManager().initLoader(CertListWidget.LOADER_ID_LINKED_CERTS,
args, mViewHolder.vLinkedCerts);
}
if (mLinkedId instanceof LinkedIdentity) {
LinkedResource res = ((LinkedIdentity) mLinkedId).mResource;
mLinkedResource = (LinkedCookieResource) res;
@ -235,30 +231,28 @@ public class LinkedIdViewFragment extends Fragment implements
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case LOADER_ID_LINKED_CERTS:
mCertAdapter.swapCursor(null);
break;
}
}
static class ViewHolder {
private final View vButtonView;
private final ViewAnimator vVerifyingContainer;
LinkedIdsAdapter.ViewHolder mLinkedIdHolder;
private ViewAnimator mButtonSwitcher;
private LinearLayout vLinkedCerts;
private CertListWidget vLinkedCerts;
private CertifyKeySpinner vKeySpinner;
private LinearLayout vLinkedVerify;
private final View vButtonVerify;
private final View vButtonRetry;
private final View vButtonConfirm;
private final View vButtonBack;
private final ViewAnimator vProgress;
private final ImageView vIcon;
private final TextView vText;
ViewHolder(View root) {
vLinkedCerts = (LinearLayout) root.findViewById(R.id.linked_id_certs);
vLinkedVerify = (LinearLayout) root.findViewById(R.id.linked_id_verify);
vLinkedCerts = (CertListWidget) root.findViewById(R.id.linked_id_certs);
vKeySpinner = (CertifyKeySpinner) root.findViewById(R.id.cert_key_spinner);
mButtonSwitcher = (ViewAnimator) root.findViewById(R.id.button_animator);
@ -269,6 +263,26 @@ public class LinkedIdViewFragment extends Fragment implements
vButtonRetry = root.findViewById(R.id.button_retry);
vButtonConfirm = root.findViewById(R.id.button_confirm);
vButtonView = root.findViewById(R.id.button_view);
vVerifyingContainer = (ViewAnimator) root.findViewById(R.id.linked_verify_container);
vProgress = (ViewAnimator) root.findViewById(R.id.linked_cert_progress);
vIcon = (ImageView) root.findViewById(R.id.linked_cert_icon);
vText = (TextView) root.findViewById(R.id.linked_cert_text);
}
void setShowVerifying(boolean show) {
int child = show ? 1 : 0;
if (vVerifyingContainer.getDisplayedChild() != child) {
vVerifyingContainer.setDisplayedChild(child);
}
if (!show) {
vKeySpinner.setVisibility(View.GONE);
}
}
void setShowProgress(boolean show) {
vProgress.setDisplayedChild(show ? 0 : 1);
}
}
@ -310,21 +324,6 @@ public class LinkedIdViewFragment extends Fragment implements
return root;
}
static class ViewHolderCert {
final ViewAnimator vProgress;
final ImageView vIcon;
final TextView vText;
ViewHolderCert(View view) {
vProgress = (ViewAnimator) view.findViewById(R.id.linked_cert_progress);
vIcon = (ImageView) view.findViewById(R.id.linked_cert_icon);
vText = (TextView) view.findViewById(R.id.linked_cert_text);
}
void setShowProgress(boolean show) {
vProgress.setDisplayedChild(show ? 0 : 1);
}
}
void showButton(int which) {
if (mViewHolder.mButtonSwitcher.getDisplayedChild() == which) {
return;
@ -342,20 +341,11 @@ public class LinkedIdViewFragment extends Fragment implements
mInProgress = true;
}
// is there a current certification? if not create a new one
final ViewHolderCert holder;
if (mCurrentCert == null) {
mCurrentCert = mInflater.inflate(R.layout.linked_id_cert, null);
holder = new ViewHolderCert(mCurrentCert);
mCurrentCert.setTag(holder);
mViewHolder.vLinkedVerify.addView(mCurrentCert);
} else {
holder = (ViewHolderCert) mCurrentCert.getTag();
}
mViewHolder.setShowVerifying(true);
mViewHolder.vKeySpinner.setVisibility(View.GONE);
holder.setShowProgress(true);
holder.vText.setText("Verifying…");
mViewHolder.setShowProgress(true);
mViewHolder.vText.setText("Verifying…");
new AsyncTask<Void,Void,LinkedVerifyResult>() {
@Override
@ -376,13 +366,13 @@ public class LinkedIdViewFragment extends Fragment implements
@Override
protected void onPostExecute(LinkedVerifyResult result) {
holder.setShowProgress(false);
mViewHolder.setShowProgress(false);
if (result.success()) {
holder.vText.setText("Ok");
mViewHolder.vText.setText("Ok");
setupForConfirmation();
} else {
showButton(1);
holder.vText.setText("Error");
mViewHolder.vText.setText("Error");
}
mInProgress = false;
}

View File

@ -0,0 +1,131 @@
package org.sufficientlysecure.keychain.ui.widget;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import android.widget.ViewAnimator;
import com.ocpsoft.pretty.time.PrettyTime;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
public class CertListWidget extends ViewAnimator
implements LoaderManager.LoaderCallbacks<Cursor> {
public static final int LOADER_ID_LINKED_CERTS = 38572;
public static final String ARG_URI = "uri";
public static final String ARG_RANK = "rank";
// These are the rows that we will retrieve.
static final String[] CERTS_PROJECTION = new String[]{
KeychainContract.Certs._ID,
KeychainContract.Certs.MASTER_KEY_ID,
KeychainContract.Certs.VERIFIED,
KeychainContract.Certs.TYPE,
KeychainContract.Certs.RANK,
KeychainContract.Certs.KEY_ID_CERTIFIER,
KeychainContract.Certs.USER_ID,
KeychainContract.Certs.SIGNER_UID,
KeychainContract.Certs.CREATION
};
public static final int INDEX_MASTER_KEY_ID = 1;
public static final int INDEX_VERIFIED = 2;
public static final int INDEX_TYPE = 3;
public static final int INDEX_RANK = 4;
public static final int INDEX_KEY_ID_CERTIFIER = 5;
public static final int INDEX_USER_ID = 6;
public static final int INDEX_SIGNER_UID = 7;
public static final int INDEX_CREATION = 8;
private TextView vCollapsed;
private View vExpanded;
private View vExpandButton;
public CertListWidget(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
View root = getRootView();
vCollapsed = (TextView) root.findViewById(R.id.cert_collapsed_list);
vExpanded = root.findViewById(R.id.cert_expanded_list);
vExpandButton = root.findViewById(R.id.cert_expand_button);
// for now
vExpandButton.setVisibility(View.GONE);
}
void setExpanded(boolean expanded) {
setDisplayedChild(expanded ? 1 : 0);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri = args.getParcelable(ARG_URI);
int rank = args.getInt(ARG_RANK);
Uri uri = Certs.buildLinkedIdCertsUri(baseUri, rank);
return new CursorLoader(getContext(), uri,
CERTS_PROJECTION, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data == null || !data.moveToFirst()) {
return;
}
setVisibility(View.VISIBLE);
// TODO support external certificates
Date userCert = null;
while (!data.isAfterLast()) {
int verified = data.getInt(INDEX_VERIFIED);
Date creation = new Date(data.getLong(INDEX_CREATION) * 1000);
if (verified == Certs.VERIFIED_SECRET) {
if (userCert == null || userCert.after(creation)) {
userCert = creation;
}
}
data.moveToNext();
}
if (userCert != null) {
PrettyTime format = new PrettyTime();
vCollapsed.setText("You verified and confirmed this identity "
+ format.format(userCert) + ".");
} else {
vCollapsed.setText("This identity is not yet verified or confirmed.");
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
setVisibility(View.GONE);
}
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<org.sufficientlysecure.keychain.ui.widget.CertListWidget
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:id="@+id/linked_id_certs">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:minHeight="?android:attr/listPreferredItemHeight"
>
<TextView
android:id="@+id/cert_collapsed_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center_vertical"
android:layout_weight="1"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_expand_more_black_24dp"
android:id="@+id/cert_expand_button"
android:padding="4dp"
/>
</LinearLayout>
<ListView
android:id="@+id/cert_expanded_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ListView>
</org.sufficientlysecure.keychain.ui.widget.CertListWidget>

View File

@ -32,21 +32,68 @@
<include layout="@layout/linked_id_item" />
<LinearLayout
<ViewAnimator
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:id="@+id/linked_id_certs">
android:id="@+id/linked_verify_container"
android:inAnimation="@anim/fade_in"
android:outAnimation="@anim/fade_out">
<include layout="@layout/cert_list_widget" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:singleLine="true">
<LinearLayout
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:layout_width="0dip"
android:layout_marginLeft="16dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="@+id/linked_cert_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Verifying…"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<ViewAnimator
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_gravity="center"
android:id="@+id/linked_cert_progress"
android:inAnimation="@anim/fade_in"
android:outAnimation="@anim/fade_out">
<ProgressBar
android:layout_width="22dp"
android:layout_height="22dp"
android:indeterminate="true"
/>
<ImageView
android:layout_width="22dp"
android:layout_height="wrap_content"
android:src="@drawable/status_signature_unknown_cutout_24dp"
android:id="@+id/linked_cert_icon"
/>
</ViewAnimator>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:id="@+id/linked_id_verify">
</LinearLayout>
</ViewAnimator>
<org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner
android:layout_marginLeft="14dp"