move linked identities into loader structure
This commit is contained in:
parent
8044586071
commit
7fc805d70c
|
@ -284,6 +284,10 @@ public class KeychainContract {
|
|||
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build();
|
||||
}
|
||||
|
||||
public static Uri buildLinkedIdsUri(long masterKeyId) {
|
||||
return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_LINKED_IDS).build();
|
||||
}
|
||||
|
||||
public static Uri buildLinkedIdsUri(Uri uri) {
|
||||
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_LINKED_IDS).build();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
* Copyright (C) 2017 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -21,29 +20,47 @@ package org.sufficientlysecure.keychain.ui.adapter;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.linked.UriAttribute;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.ViewHolder;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.IdentityInfo;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.LinkedIdInfo;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.UserIdInfo;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
|
||||
|
||||
|
||||
public class IdentityAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||
private static final int VIEW_TYPE_USER_ID = 0;
|
||||
private static final int VIEW_TYPE_LINKED_ID = 1;
|
||||
|
||||
|
||||
private final Context context;
|
||||
private final LayoutInflater layoutInflater;
|
||||
private final boolean isSecret;
|
||||
|
||||
private List<IdentityInfo> data;
|
||||
|
||||
public IdentityAdapter(Context context) {
|
||||
|
||||
public IdentityAdapter(Context context, boolean isSecret) {
|
||||
super();
|
||||
this.layoutInflater = LayoutInflater.from(context);
|
||||
this.context = context;
|
||||
this.isSecret = isSecret;
|
||||
}
|
||||
|
||||
public void setData(List<IdentityInfo> data) {
|
||||
|
@ -56,36 +73,37 @@ public class IdentityAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
IdentityInfo info = data.get(position);
|
||||
|
||||
if (info.name != null) {
|
||||
holder.vName.setText(info.name);
|
||||
int viewType = getItemViewType(position);
|
||||
if (viewType == VIEW_TYPE_USER_ID) {
|
||||
((UserIdViewHolder) holder).bind((UserIdInfo) info);
|
||||
} else if (viewType == VIEW_TYPE_LINKED_ID) {
|
||||
((LinkedIdViewHolder) holder).bind(context, (LinkedIdInfo) info, isSecret);
|
||||
} else {
|
||||
holder.vName.setText(R.string.user_id_no_name);
|
||||
}
|
||||
if (info.email != null) {
|
||||
holder.vAddress.setText(info.email);
|
||||
holder.vAddress.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.vAddress.setVisibility(View.GONE);
|
||||
}
|
||||
if (info.comment != null) {
|
||||
holder.vComment.setText(info.comment);
|
||||
holder.vComment.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.vComment.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (info.isPrimary) {
|
||||
holder.vName.setTypeface(null, Typeface.BOLD);
|
||||
holder.vAddress.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
holder.vName.setTypeface(null, Typeface.NORMAL);
|
||||
holder.vAddress.setTypeface(null, Typeface.NORMAL);
|
||||
throw new IllegalStateException("unhandled identitytype!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(layoutInflater.inflate(R.layout.view_key_identity_user_id, null));
|
||||
if (viewType == VIEW_TYPE_USER_ID) {
|
||||
return new UserIdViewHolder(layoutInflater.inflate(R.layout.view_key_identity_user_id, parent, false));
|
||||
} else if (viewType == VIEW_TYPE_LINKED_ID) {
|
||||
return new LinkedIdViewHolder(layoutInflater.inflate(R.layout.linked_id_item, parent, false));
|
||||
} else {
|
||||
throw new IllegalStateException("unhandled identitytype!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
IdentityInfo info = data.get(position);
|
||||
if (info instanceof UserIdInfo) {
|
||||
return VIEW_TYPE_USER_ID;
|
||||
} else if (info instanceof LinkedIdInfo) {
|
||||
return VIEW_TYPE_LINKED_ID;
|
||||
} else {
|
||||
throw new IllegalStateException("unhandled identitytype!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,19 +111,121 @@ public class IdentityAdapter extends RecyclerView.Adapter<ViewHolder> {
|
|||
return data != null ? data.size() : 0;
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View v;
|
||||
public IdentityInfo getInfo(int position) {
|
||||
return data.get(position);
|
||||
}
|
||||
|
||||
abstract static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LinkedIdViewHolder extends ViewHolder {
|
||||
public final ImageView vVerified;
|
||||
final private ImageView vIcon;
|
||||
final private TextView vTitle;
|
||||
final private TextView vComment;
|
||||
|
||||
public LinkedIdViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
vVerified = (ImageView) view.findViewById(R.id.linked_id_certified_icon);
|
||||
vIcon = (ImageView) view.findViewById(R.id.linked_id_type_icon);
|
||||
vTitle = (TextView) view.findViewById(R.id.linked_id_title);
|
||||
vComment = (TextView) view.findViewById(R.id.linked_id_comment);
|
||||
}
|
||||
|
||||
public void bind(Context context, LinkedIdInfo info, boolean isSecret) {
|
||||
bindVerified(context, info, isSecret);
|
||||
|
||||
UriAttribute uriAttribute = info.getUriAttribute();
|
||||
bind(context, uriAttribute);
|
||||
}
|
||||
|
||||
public void bind(Context context, UriAttribute uriAttribute) {
|
||||
vTitle.setText(uriAttribute.getDisplayTitle(context));
|
||||
|
||||
String comment = uriAttribute.getDisplayComment(context);
|
||||
if (comment != null) {
|
||||
vComment.setVisibility(View.VISIBLE);
|
||||
vComment.setText(comment);
|
||||
} else {
|
||||
vComment.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
vIcon.setImageResource(uriAttribute.getDisplayIcon());
|
||||
}
|
||||
|
||||
private void bindVerified(Context context, IdentityInfo info, boolean isSecret) {
|
||||
if (!isSecret) {
|
||||
switch (info.getVerified()) {
|
||||
case Certs.VERIFIED_SECRET:
|
||||
KeyFormattingUtils.setStatusImage(context, vVerified,
|
||||
null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
case Certs.VERIFIED_SELF:
|
||||
KeyFormattingUtils.setStatusImage(context, vVerified,
|
||||
null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
default:
|
||||
KeyFormattingUtils.setStatusImage(context, vVerified,
|
||||
null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void seekAttention() {
|
||||
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||
ObjectAnimator anim = SubtleAttentionSeeker.tintText(vComment, 1000);
|
||||
anim.setStartDelay(200);
|
||||
anim.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class UserIdViewHolder extends ViewHolder {
|
||||
private final TextView vName;
|
||||
private final TextView vAddress;
|
||||
private final TextView vComment;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
private UserIdViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
vName = (TextView) view.findViewById(R.id.user_id_item_name);
|
||||
vAddress = (TextView) view.findViewById(R.id.user_id_item_address);
|
||||
vComment = (TextView) view.findViewById(R.id.user_id_item_comment);
|
||||
}
|
||||
|
||||
public void bind(UserIdInfo info) {
|
||||
if (info.getName() != null) {
|
||||
vName.setText(info.getName());
|
||||
} else {
|
||||
vName.setText(R.string.user_id_no_name);
|
||||
}
|
||||
if (info.getEmail() != null) {
|
||||
vAddress.setText(info.getEmail());
|
||||
vAddress.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vAddress.setVisibility(View.GONE);
|
||||
}
|
||||
if (info.getComment() != null) {
|
||||
vComment.setText(info.getComment());
|
||||
vComment.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vComment.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (info.isPrimary()) {
|
||||
vName.setTypeface(null, Typeface.BOLD);
|
||||
vAddress.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
vName.setTypeface(null, Typeface.NORMAL);
|
||||
vAddress.setTypeface(null, Typeface.NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
*
|
||||
* 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.adapter;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedAttribute;
|
||||
import org.sufficientlysecure.keychain.linked.UriAttribute;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
|
||||
import org.sufficientlysecure.keychain.util.FilterCursorWrapper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class LinkedIdsAdapter extends UserAttributesAdapter {
|
||||
private final boolean mIsSecret;
|
||||
protected LayoutInflater mInflater;
|
||||
WeakHashMap<Integer,UriAttribute> mLinkedIdentityCache = new WeakHashMap<>();
|
||||
|
||||
public LinkedIdsAdapter(Context context, Cursor c, int flags, boolean isSecret) {
|
||||
super(context, c, flags);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mIsSecret = isSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor swapCursor(Cursor cursor) {
|
||||
if (cursor == null) {
|
||||
return super.swapCursor(null);
|
||||
}
|
||||
FilterCursorWrapper filteredCursor = new FilterCursorWrapper(cursor) {
|
||||
@Override
|
||||
public boolean isVisible(Cursor cursor) {
|
||||
UriAttribute id = getItemAtPosition(cursor);
|
||||
return id instanceof LinkedAttribute;
|
||||
}
|
||||
};
|
||||
|
||||
return super.swapCursor(filteredCursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
|
||||
ViewHolder holder = (ViewHolder) view.getTag();
|
||||
|
||||
if (!mIsSecret) {
|
||||
int isVerified = cursor.getInt(INDEX_VERIFIED);
|
||||
switch (isVerified) {
|
||||
case Certs.VERIFIED_SECRET:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
case Certs.VERIFIED_SELF:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
default:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UriAttribute id = getItemAtPosition(cursor);
|
||||
holder.setData(mContext, id);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
view.setTransitionName(id.mUri.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public UriAttribute getItemAtPosition(Cursor cursor) {
|
||||
int rank = cursor.getInt(INDEX_RANK);
|
||||
Log.d(Constants.TAG, "requested rank: " + rank);
|
||||
|
||||
UriAttribute ret = mLinkedIdentityCache.get(rank);
|
||||
if (ret != null) {
|
||||
Log.d(Constants.TAG, "cached!");
|
||||
return ret;
|
||||
}
|
||||
Log.d(Constants.TAG, "not cached!");
|
||||
|
||||
try {
|
||||
byte[] data = cursor.getBlob(INDEX_ATTRIBUTE_DATA);
|
||||
ret = LinkedAttribute.fromAttributeData(data);
|
||||
mLinkedIdentityCache.put(rank, ret);
|
||||
return ret;
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "could not read linked identity subpacket data", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriAttribute getItem(int position) {
|
||||
Cursor cursor = getCursor();
|
||||
cursor.moveToPosition(position);
|
||||
return getItemAtPosition(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
View v = mInflater.inflate(R.layout.linked_id_item, null);
|
||||
ViewHolder holder = new ViewHolder(v);
|
||||
v.setTag(holder);
|
||||
return v;
|
||||
}
|
||||
|
||||
// don't show revoked user ids, irrelevant for average users
|
||||
public static final String LINKED_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
|
||||
|
||||
public static CursorLoader createLoader(Context context, Uri dataUri) {
|
||||
Uri baseUri = UserPackets.buildLinkedIdsUri(dataUri);
|
||||
return new CursorLoader(context, baseUri,
|
||||
UserIdsAdapter.USER_PACKETS_PROJECTION, LINKED_IDS_WHERE, null, null);
|
||||
}
|
||||
|
||||
public LinkedIdViewFragment getLinkedIdFragment(int position, long masterKeyId) throws IOException {
|
||||
Cursor c = getCursor();
|
||||
c.moveToPosition(position);
|
||||
int rank = c.getInt(UserIdsAdapter.INDEX_RANK);
|
||||
|
||||
Uri dataUri = UserPackets.buildLinkedIdsUri(KeyRings.buildGenericKeyRingUri(masterKeyId));
|
||||
return LinkedIdViewFragment.newInstance(dataUri, rank, mIsSecret, masterKeyId);
|
||||
}
|
||||
|
||||
public static class ViewHolder {
|
||||
final public ImageView vVerified;
|
||||
final public ImageView vIcon;
|
||||
final public TextView vTitle;
|
||||
final public TextView vComment;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
vVerified = (ImageView) view.findViewById(R.id.linked_id_certified_icon);
|
||||
vIcon = (ImageView) view.findViewById(R.id.linked_id_type_icon);
|
||||
vTitle = (TextView) view.findViewById(R.id.linked_id_title);
|
||||
vComment = (TextView) view.findViewById(R.id.linked_id_comment);
|
||||
}
|
||||
|
||||
public void setData(Context context, UriAttribute id) {
|
||||
|
||||
vTitle.setText(id.getDisplayTitle(context));
|
||||
|
||||
String comment = id.getDisplayComment(context);
|
||||
if (comment != null) {
|
||||
vComment.setVisibility(View.VISIBLE);
|
||||
vComment.setText(comment);
|
||||
} else {
|
||||
vComment.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
vIcon.setImageResource(id.getDisplayIcon());
|
||||
|
||||
}
|
||||
|
||||
public void seekAttention() {
|
||||
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||
ObjectAnimator anim = SubtleAttentionSeeker.tintText(vComment, 1000);
|
||||
anim.setStartDelay(200);
|
||||
anim.start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.sufficientlysecure.keychain.ui.keyview;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
|
@ -50,11 +51,11 @@ import android.widget.ViewAnimator;
|
|||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Constants.key;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedAttribute;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedResource;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
|
||||
import org.sufficientlysecure.keychain.linked.UriAttribute;
|
||||
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
|
@ -63,7 +64,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
|||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment.ViewHolder.VerifyState;
|
||||
|
@ -217,7 +218,7 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
|
|||
mViewHolder.mLinkedIdHolder.vVerified.setImageResource(R.drawable.octo_link_24dp);
|
||||
}
|
||||
|
||||
mViewHolder.mLinkedIdHolder.setData(mContext, mLinkedId);
|
||||
mViewHolder.mLinkedIdHolder.bind(mContext, mLinkedId);
|
||||
|
||||
setShowVerifying(false);
|
||||
|
||||
|
@ -256,7 +257,7 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
|
|||
private final ViewAnimator vVerifyingContainer;
|
||||
private final ViewAnimator vItemCertified;
|
||||
private final View vKeySpinnerContainer;
|
||||
LinkedIdsAdapter.ViewHolder mLinkedIdHolder;
|
||||
IdentityAdapter.LinkedIdViewHolder mLinkedIdHolder;
|
||||
|
||||
private ViewAnimator vButtonSwitcher;
|
||||
private CertListWidget vLinkedCerts;
|
||||
|
@ -274,7 +275,7 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
|
|||
vKeySpinnerContainer = root.findViewById(R.id.cert_key_spincontainer);
|
||||
vButtonSwitcher = (ViewAnimator) root.findViewById(R.id.button_animator);
|
||||
|
||||
mLinkedIdHolder = new LinkedIdsAdapter.ViewHolder(root);
|
||||
mLinkedIdHolder = new IdentityAdapter.LinkedIdViewHolder(root);
|
||||
|
||||
vButtonVerify = root.findViewById(R.id.button_verify);
|
||||
vButtonRetry = root.findViewById(R.id.button_retry);
|
||||
|
|
|
@ -35,30 +35,25 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
|||
import org.sufficientlysecure.keychain.ui.base.LoaderFragment;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsFragMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.SystemContactPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.ViewKeyMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.view.IdentitiesCardView;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.view.KeyHealthView;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
|
||||
public class ViewKeyFragment extends LoaderFragment implements LinkedIdsFragMvpView, ViewKeyMvpView {
|
||||
public class ViewKeyFragment extends LoaderFragment implements ViewKeyMvpView {
|
||||
public static final String ARG_MASTER_KEY_ID = "master_key_id";
|
||||
public static final String ARG_IS_SECRET = "is_secret";
|
||||
|
||||
boolean mIsSecret = false;
|
||||
|
||||
private static final int LOADER_ID_USER_IDS = 1;
|
||||
private static final int LOADER_ID_LINKED_IDS = 2;
|
||||
private static final int LOADER_ID_LINKED_CONTACT = 3;
|
||||
private static final int LOADER_ID_SUBKEY_STATUS = 4;
|
||||
private static final int LOADER_IDENTITIES = 1;
|
||||
private static final int LOADER_ID_LINKED_CONTACT = 2;
|
||||
private static final int LOADER_ID_SUBKEY_STATUS = 3;
|
||||
|
||||
private IdentitiesCardView mIdentitiesCardView;
|
||||
private IdentitiesPresenter mIdentitiesPresenter;
|
||||
private LinkedIdentitiesPresenter mLinkedIdentitiesPresenter;
|
||||
|
||||
SystemContactCardView mSystemContactCard;
|
||||
SystemContactPresenter mSystemContactPresenter;
|
||||
|
@ -102,15 +97,9 @@ public class ViewKeyFragment extends LoaderFragment implements LinkedIdsFragMvpV
|
|||
mIsSecret = getArguments().getBoolean(ARG_IS_SECRET);
|
||||
|
||||
mIdentitiesPresenter = new IdentitiesPresenter(
|
||||
getContext(), mIdentitiesCardView, this, LOADER_ID_USER_IDS, masterKeyId, mIsSecret);
|
||||
getContext(), mIdentitiesCardView, this, LOADER_IDENTITIES, masterKeyId, mIsSecret);
|
||||
mIdentitiesPresenter.startLoader(getLoaderManager());
|
||||
|
||||
if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) {
|
||||
mLinkedIdentitiesPresenter = new LinkedIdentitiesPresenter(
|
||||
getContext(), mIdentitiesCardView, this, LOADER_ID_LINKED_IDS, masterKeyId, mIsSecret);
|
||||
mLinkedIdentitiesPresenter.startLoader(getLoaderManager());
|
||||
}
|
||||
|
||||
mSystemContactPresenter = new SystemContactPresenter(
|
||||
getContext(), mSystemContactCard, LOADER_ID_LINKED_CONTACT, masterKeyId, mIsSecret);
|
||||
mSystemContactPresenter.startLoader(getLoaderManager());
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.sufficientlysecure.keychain.ui.keyview.loader;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -25,10 +26,14 @@ import java.util.List;
|
|||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.linked.LinkedAttribute;
|
||||
import org.sufficientlysecure.keychain.linked.UriAttribute;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.IdentityInfo;
|
||||
|
||||
|
@ -63,34 +68,84 @@ public class IdentityLoader extends AsyncTaskLoader<List<IdentityInfo>> {
|
|||
|
||||
private final ContentResolver contentResolver;
|
||||
private final long masterKeyId;
|
||||
private final boolean showLinkedIds;
|
||||
|
||||
private List<IdentityInfo> cachedResult;
|
||||
|
||||
|
||||
public IdentityLoader(Context context, ContentResolver contentResolver, long masterKeyId) {
|
||||
public IdentityLoader(Context context, ContentResolver contentResolver, long masterKeyId, boolean showLinkedIds) {
|
||||
super(context);
|
||||
|
||||
this.contentResolver = contentResolver;
|
||||
this.masterKeyId = masterKeyId;
|
||||
this.showLinkedIds = showLinkedIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IdentityInfo> loadInBackground() {
|
||||
ArrayList<IdentityInfo> identities = new ArrayList<>();
|
||||
|
||||
if (showLinkedIds) {
|
||||
loadLinkedIds(identities);
|
||||
}
|
||||
loadUserIds(identities);
|
||||
|
||||
return Collections.unmodifiableList(identities);
|
||||
}
|
||||
|
||||
private void loadLinkedIds(ArrayList<IdentityInfo> identities) {
|
||||
Cursor cursor = contentResolver.query(UserPackets.buildLinkedIdsUri(masterKeyId),
|
||||
USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null);
|
||||
if (cursor == null) {
|
||||
Log.e(Constants.TAG, "Error loading key items!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
int rank = cursor.getInt(INDEX_RANK);
|
||||
int verified = cursor.getInt(INDEX_VERIFIED);
|
||||
boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
|
||||
|
||||
byte[] data = cursor.getBlob(INDEX_ATTRIBUTE_DATA);
|
||||
try {
|
||||
UriAttribute uriAttribute = LinkedAttribute.fromAttributeData(data);
|
||||
if (uriAttribute instanceof LinkedAttribute) {
|
||||
LinkedIdInfo identityInfo = LinkedIdInfo.create(rank, verified, isPrimary, uriAttribute);
|
||||
identities.add(identityInfo);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Failed parsing uri attribute", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadUserIds(ArrayList<IdentityInfo> identities) {
|
||||
Cursor cursor = contentResolver.query(UserPackets.buildUserIdsUri(masterKeyId),
|
||||
USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null);
|
||||
if (cursor == null) {
|
||||
Log.e(Constants.TAG, "Error loading key items!");
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ArrayList<IdentityInfo> identities = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
IdentityInfo identityInfo = new IdentityInfo(masterKeyId, cursor);
|
||||
identities.add(identityInfo);
|
||||
}
|
||||
int rank = cursor.getInt(INDEX_RANK);
|
||||
int verified = cursor.getInt(INDEX_VERIFIED);
|
||||
boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
|
||||
|
||||
return Collections.unmodifiableList(identities);
|
||||
if (!cursor.isNull(INDEX_NAME) || !cursor.isNull(INDEX_EMAIL)) {
|
||||
String name = cursor.getString(INDEX_NAME);
|
||||
String email = cursor.getString(INDEX_EMAIL);
|
||||
String comment = cursor.getString(INDEX_COMMENT);
|
||||
|
||||
IdentityInfo identityInfo = UserIdInfo.create(rank, verified, isPrimary, name, email, comment);
|
||||
identities.add(identityInfo);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
@ -116,36 +171,41 @@ public class IdentityLoader extends AsyncTaskLoader<List<IdentityInfo>> {
|
|||
}
|
||||
}
|
||||
|
||||
public static class IdentityInfo {
|
||||
final int position;
|
||||
public interface IdentityInfo {
|
||||
int getRank();
|
||||
int getVerified();
|
||||
boolean isPrimary();
|
||||
}
|
||||
|
||||
public final int verified;
|
||||
public final byte[] data;
|
||||
public final String name;
|
||||
public final String email;
|
||||
public final String comment;
|
||||
@AutoValue
|
||||
public abstract static class UserIdInfo implements IdentityInfo {
|
||||
public abstract int getRank();
|
||||
public abstract int getVerified();
|
||||
public abstract boolean isPrimary();
|
||||
|
||||
public boolean isPrimary;
|
||||
@Nullable
|
||||
public abstract String getName();
|
||||
@Nullable
|
||||
public abstract String getEmail();
|
||||
@Nullable
|
||||
public abstract String getComment();
|
||||
|
||||
IdentityInfo(long masterKeyId, Cursor cursor) {
|
||||
position = cursor.getPosition();
|
||||
static UserIdInfo create(int rank, int verified, boolean isPrimary, String name, String email,
|
||||
String comment) {
|
||||
return new AutoValue_IdentityLoader_UserIdInfo(rank, verified, isPrimary, name, email, comment);
|
||||
}
|
||||
}
|
||||
|
||||
verified = cursor.getInt(INDEX_VERIFIED);
|
||||
if (cursor.isNull(INDEX_NAME)) {
|
||||
data = cursor.getBlob(INDEX_ATTRIBUTE_DATA);
|
||||
@AutoValue
|
||||
public abstract static class LinkedIdInfo implements IdentityInfo {
|
||||
public abstract int getRank();
|
||||
public abstract int getVerified();
|
||||
public abstract boolean isPrimary();
|
||||
|
||||
name = null;
|
||||
email = null;
|
||||
comment = null;
|
||||
} else {
|
||||
data = null;
|
||||
public abstract UriAttribute getUriAttribute();
|
||||
|
||||
name = cursor.getString(INDEX_NAME);
|
||||
email = cursor.getString(INDEX_EMAIL);
|
||||
comment = cursor.getString(INDEX_COMMENT);
|
||||
}
|
||||
|
||||
isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
|
||||
static LinkedIdInfo create(int rank, int verified, boolean isPrimary, UriAttribute uriAttribute) {
|
||||
return new AutoValue_IdentityLoader_LinkedIdInfo(rank, verified, isPrimary, uriAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,20 +18,32 @@
|
|||
package org.sufficientlysecure.keychain.ui.keyview.presenter;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.ui.EditIdentitiesActivity;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.IdentityInfo;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.LinkedIdInfo;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityLoader.UserIdInfo;
|
||||
import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
|
||||
public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>> {
|
||||
|
@ -55,7 +67,7 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
this.masterKeyId = masterKeyId;
|
||||
this.isSecret = isSecret;
|
||||
|
||||
identitiesAdapter = new IdentityAdapter(context);
|
||||
identitiesAdapter = new IdentityAdapter(context, isSecret);
|
||||
view.setIdentitiesAdapter(identitiesAdapter);
|
||||
|
||||
view.setEditIdentitiesButtonVisible(isSecret);
|
||||
|
@ -63,13 +75,18 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
view.setIdentitiesCardListener(new IdentitiesCardListener() {
|
||||
@Override
|
||||
public void onIdentityItemClick(int position) {
|
||||
showUserIdInfo(position);
|
||||
showIdentityInfo(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickEditIdentities() {
|
||||
editIdentities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickAddIdentity() {
|
||||
addLinkedIdentity();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -79,7 +96,8 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
|
||||
@Override
|
||||
public Loader<List<IdentityInfo>> onCreateLoader(int id, Bundle args) {
|
||||
return new IdentityLoader(context, context.getContentResolver(), masterKeyId);
|
||||
boolean showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities();
|
||||
return new IdentityLoader(context, context.getContentResolver(), masterKeyId, showLinkedIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,14 +111,35 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
identitiesAdapter.setData(null);
|
||||
}
|
||||
|
||||
private void showUserIdInfo(final int position) {
|
||||
// if (!isSecret) {
|
||||
// final boolean isRevoked = identitiesAdapter.getIsRevoked(position);
|
||||
// final int isVerified = identitiesAdapter.getIsVerified(position);
|
||||
//
|
||||
// UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(isRevoked, isVerified);
|
||||
// viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog");
|
||||
// }
|
||||
private void showIdentityInfo(final int position) {
|
||||
IdentityInfo info = identitiesAdapter.getInfo(position);
|
||||
if (info instanceof LinkedIdInfo) {
|
||||
showLinkedId((LinkedIdInfo) info);
|
||||
} else if (info instanceof UserIdInfo) {
|
||||
showUserIdInfo((UserIdInfo) info);
|
||||
}
|
||||
}
|
||||
|
||||
private void showLinkedId(final LinkedIdInfo info) {
|
||||
final LinkedIdViewFragment frag;
|
||||
try {
|
||||
Uri dataUri = UserPackets.buildLinkedIdsUri(KeyRings.buildGenericKeyRingUri(masterKeyId));
|
||||
frag = LinkedIdViewFragment.newInstance(dataUri, info.getRank(), isSecret, masterKeyId);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "IOException", e);
|
||||
return;
|
||||
}
|
||||
|
||||
viewKeyMvpView.switchToFragment(frag, "linked_id");
|
||||
}
|
||||
|
||||
private void showUserIdInfo(UserIdInfo info) {
|
||||
if (!isSecret) {
|
||||
final int isVerified = info.getVerified();
|
||||
|
||||
UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, isVerified);
|
||||
viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog");
|
||||
}
|
||||
}
|
||||
|
||||
private void editIdentities() {
|
||||
|
@ -109,6 +148,12 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
viewKeyMvpView.startActivityAndShowResultSnackbar(editIntent);
|
||||
}
|
||||
|
||||
private void addLinkedIdentity() {
|
||||
Intent intent = new Intent(context, LinkedIdWizard.class);
|
||||
intent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public interface IdentitiesMvpView {
|
||||
void setIdentitiesAdapter(IdentityAdapter userIdsAdapter);
|
||||
void setIdentitiesCardListener(IdentitiesCardListener identitiesCardListener);
|
||||
|
@ -117,6 +162,8 @@ public class IdentitiesPresenter implements LoaderCallbacks<List<IdentityInfo>>
|
|||
|
||||
public interface IdentitiesCardListener {
|
||||
void onIdentityItemClick(int position);
|
||||
|
||||
void onClickEditIdentities();
|
||||
void onClickAddIdentity();
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
*
|
||||
* 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.keyview.presenter;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment;
|
||||
import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
|
||||
public class LinkedIdentitiesPresenter implements LoaderCallbacks<Cursor> {
|
||||
private final Context context;
|
||||
private final LinkedIdsMvpView view;
|
||||
private final int loaderId;
|
||||
private final LinkedIdsFragMvpView fragView;
|
||||
|
||||
private LinkedIdsAdapter linkedIdsAdapter;
|
||||
|
||||
private final long masterKeyId;
|
||||
private final boolean isSecret;
|
||||
|
||||
public LinkedIdentitiesPresenter(
|
||||
Context context, LinkedIdsMvpView view, LinkedIdsFragMvpView fragView, int loaderId, long masterKeyId, boolean isSecret) {
|
||||
this.context = context;
|
||||
this.view = view;
|
||||
this.fragView = fragView;
|
||||
this.loaderId = loaderId;
|
||||
|
||||
this.masterKeyId = masterKeyId;
|
||||
this.isSecret = isSecret;
|
||||
|
||||
linkedIdsAdapter = new LinkedIdsAdapter(context, null, 0, isSecret);
|
||||
view.setLinkedIdsAdapter(linkedIdsAdapter);
|
||||
|
||||
view.setSystemContactClickListener(new LinkedIdsClickListener() {
|
||||
@Override
|
||||
public void onLinkedIdItemClick(int position) {
|
||||
showLinkedId(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickAddIdentity() {
|
||||
addLinkedIdentity();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void startLoader(LoaderManager loaderManager) {
|
||||
loaderManager.restartLoader(loaderId, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return LinkedIdsAdapter.createLoader(context, KeyRings.buildUnifiedKeyRingUri(masterKeyId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||
linkedIdsAdapter.swapCursor(data);
|
||||
|
||||
boolean anyDataShown = data.getCount() > 0;
|
||||
view.setShowLinkedIdDivider(anyDataShown);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader loader) {
|
||||
linkedIdsAdapter.swapCursor(null);
|
||||
view.setShowLinkedIdDivider(false);
|
||||
}
|
||||
|
||||
private void showLinkedId(final int position) {
|
||||
final LinkedIdViewFragment frag;
|
||||
try {
|
||||
frag = linkedIdsAdapter.getLinkedIdFragment(position, masterKeyId);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "IOException", e);
|
||||
return;
|
||||
}
|
||||
|
||||
fragView.switchToFragment(frag, "linked_id");
|
||||
}
|
||||
|
||||
public interface LinkedIdsMvpView {
|
||||
void setSystemContactClickListener(LinkedIdsClickListener linkedIdsClickListener);
|
||||
void setLinkedIdsAdapter(LinkedIdsAdapter linkedIdsAdapter);
|
||||
|
||||
void setShowLinkedIdDivider(boolean show);
|
||||
}
|
||||
|
||||
public interface LinkedIdsFragMvpView {
|
||||
void switchToFragment(Fragment frag, String backStackName);
|
||||
}
|
||||
|
||||
public interface LinkedIdsClickListener {
|
||||
void onLinkedIdItemClick(int position);
|
||||
void onClickAddIdentity();
|
||||
}
|
||||
|
||||
private void addLinkedIdentity() {
|
||||
Intent intent = new Intent(context, LinkedIdWizard.class);
|
||||
intent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -3,9 +3,12 @@ package org.sufficientlysecure.keychain.ui.keyview.presenter;
|
|||
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
|
||||
public interface ViewKeyMvpView {
|
||||
void switchToFragment(Fragment frag, String backStackName);
|
||||
|
||||
void startActivityAndShowResultSnackbar(Intent intent);
|
||||
void showDialogFragment(DialogFragment dialogFragment, final String tag);
|
||||
void setContentShown(boolean show, boolean animate);
|
||||
|
|
|
@ -25,27 +25,19 @@ import android.support.v7.widget.RecyclerView;
|
|||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesCardListener;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsClickListener;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.util.recyclerview.DividerItemDecoration;
|
||||
import org.sufficientlysecure.keychain.ui.util.recyclerview.RecyclerItemClickListener;
|
||||
|
||||
|
||||
public class IdentitiesCardView extends CardView implements IdentitiesMvpView, LinkedIdsMvpView {
|
||||
private final ListView vLinkedIds;
|
||||
public class IdentitiesCardView extends CardView implements IdentitiesMvpView {
|
||||
private final RecyclerView vIdentities;
|
||||
private final View vLinkedIdsDivider;
|
||||
|
||||
private LinkedIdsClickListener linkedIdsClickListener;
|
||||
private IdentitiesCardListener identitiesCardListener;
|
||||
|
||||
public IdentitiesCardView(Context context, AttributeSet attrs) {
|
||||
|
@ -55,6 +47,7 @@ public class IdentitiesCardView extends CardView implements IdentitiesMvpView, L
|
|||
|
||||
vIdentities = (RecyclerView) view.findViewById(R.id.view_key_user_ids);
|
||||
vIdentities.setLayoutManager(new LinearLayoutManager(context));
|
||||
vIdentities.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL_LIST));
|
||||
|
||||
Button userIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit);
|
||||
userIdsEditButton.setOnClickListener(new OnClickListener() {
|
||||
|
@ -76,28 +69,16 @@ public class IdentitiesCardView extends CardView implements IdentitiesMvpView, L
|
|||
}
|
||||
}));
|
||||
|
||||
vLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids);
|
||||
Button linkedIdsAddButton = (Button) view.findViewById(R.id.view_key_card_linked_ids_add);
|
||||
|
||||
linkedIdsAddButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (linkedIdsClickListener != null) {
|
||||
linkedIdsClickListener.onClickAddIdentity();
|
||||
if (identitiesCardListener != null) {
|
||||
identitiesCardListener.onClickAddIdentity();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
vLinkedIds.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (linkedIdsClickListener != null) {
|
||||
linkedIdsClickListener.onLinkedIdItemClick(position);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
vLinkedIdsDivider = view.findViewById(R.id.view_key_lid_divider);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,19 +95,4 @@ public class IdentitiesCardView extends CardView implements IdentitiesMvpView, L
|
|||
public void setEditIdentitiesButtonVisible(boolean show) {
|
||||
findViewById(R.id.view_key_card_user_ids_buttons).setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemContactClickListener(LinkedIdsClickListener linkedIdsClickListener) {
|
||||
this.linkedIdsClickListener = linkedIdsClickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLinkedIdsAdapter(LinkedIdsAdapter linkedIdsAdapter) {
|
||||
vLinkedIds.setAdapter(linkedIdsAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShowLinkedIdDivider(boolean show) {
|
||||
vLinkedIdsDivider.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
|||
final int right = parent.getWidth() - parent.getPaddingRight();
|
||||
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
for (int i = 0; i < childCount -1; i++) {
|
||||
final View child = parent.getChildAt(i);
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
|
@ -83,7 +83,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration {
|
|||
final int bottom = parent.getHeight() - parent.getPaddingBottom();
|
||||
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
for (int i = 0; i < childCount -1; i++) {
|
||||
final View child = parent.getChildAt(i);
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
|
|
|
@ -12,21 +12,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/section_user_ids" />
|
||||
|
||||
<org.sufficientlysecure.keychain.ui.widget.FixedListView
|
||||
android:id="@+id/view_key_linked_ids"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dip"
|
||||
android:id="@+id/view_key_lid_divider"
|
||||
android:background="?android:attr/listDivider"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/view_key_user_ids"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,31 +1,33 @@
|
|||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp">
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_id_item_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="alice@example.com"
|
||||
tools:text="alice@example.com"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_id_item_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Alice"
|
||||
tools:text="Alice"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_id_item_comment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="comment"
|
||||
tools:text="comment"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
Loading…
Reference in a new issue