From d645c435fd2205eb5710f946dc2ed6a4338f3da1 Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 5 Jan 2016 03:38:26 +0000 Subject: [PATCH 1/9] Identicon generation code from Android-Identicons Source: https://github.com/saiimons/Android-Identicons License: Apache License, Version 2.0 --- .../identicons/AsymmetricIdenticon.java | 71 +++++++++++ .../android/identicons/IdenticonBase.java | 120 ++++++++++++++++++ .../android/identicons/IdenticonDrawable.java | 85 +++++++++++++ .../android/identicons/IdenticonView.java | 118 +++++++++++++++++ .../identicons/SymmetricIdenticon.java | 81 ++++++++++++ 5 files changed, 475 insertions(+) create mode 100644 briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonBase.java create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonDrawable.java create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonView.java create mode 100644 briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java diff --git a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java new file mode 100644 index 000000000..bce32ff9e --- /dev/null +++ b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java @@ -0,0 +1,71 @@ +package im.delight.android.identicons; + +/** + * Copyright 2014 www.delight.im + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; + +public class AsymmetricIdenticon extends IdenticonView { + + private IdenticonBase mDelegate; + + public AsymmetricIdenticon(Context context) { + super(context); + initDelegate(); + } + + public AsymmetricIdenticon(Context context, AttributeSet attrs) { + super(context, attrs); + initDelegate(); + } + + public AsymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initDelegate(); + } + + @Override + protected IdenticonBase getDelegate() { + return mDelegate; + } + + private void initDelegate() { + mDelegate = new IdenticonBase() { + @Override + protected int getRowCount() { + return 4; + } + + @Override + protected int getColumnCount() { + return 4; + } + + @Override + protected boolean isCellVisible(int row, int column) { + return getByte(3 + row * getColumnCount() + column) >= 0; + } + + @Override + protected int getIconColor() { + return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128); + } + }; + } + +} diff --git a/briar-android/src/im/delight/android/identicons/IdenticonBase.java b/briar-android/src/im/delight/android/identicons/IdenticonBase.java new file mode 100644 index 000000000..a1a5d5dd3 --- /dev/null +++ b/briar-android/src/im/delight/android/identicons/IdenticonBase.java @@ -0,0 +1,120 @@ +package im.delight.android.identicons; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; + +import java.security.MessageDigest; + +/** + * Created by saiimons on 05/10/14. + */ +public abstract class IdenticonBase { + private static final String HASH_ALGORITHM = "SHA-256"; + + + private final int mRowCount; + private final int mColumnCount; + private final Paint mPaint; + private volatile int mCellWidth; + private volatile int mCellHeight; + private volatile byte[] mHash; + private volatile int[][] mColors; + private volatile boolean mReady; + + public IdenticonBase() { + mRowCount = getRowCount(); + mColumnCount = getColumnCount(); + mPaint = new Paint(); + + mPaint.setStyle(Paint.Style.FILL); + mPaint.setAntiAlias(true); + mPaint.setDither(true); + } + + public static byte[] getHash(String input) { + byte[] mHash; + // if the input was null + if (input == null) { + // we can't create a hash value and have nothing to show (draw to the view) + mHash = null; + } + // if the input was a proper string (non-null) + else { + // generate a hash from the string to get unique but deterministic byte values + try { + final MessageDigest digest = java.security.MessageDigest.getInstance(HASH_ALGORITHM); + digest.update(input == null ? new byte[0] : input.getBytes()); + mHash = digest.digest(); + } catch (Exception e) { + mHash = null; + } + } + return mHash; + } + + protected void setupColors() { + mColors = new int[mRowCount][mColumnCount]; + int colorVisible = getIconColor(); + + for (int r = 0; r < mRowCount; r++) { + for (int c = 0; c < mColumnCount; c++) { + if (isCellVisible(r, c)) { + mColors[r][c] = colorVisible; + } else { + mColors[r][c] = Color.TRANSPARENT; + } + } + } + } + + public void show(String input) { + if(input != null) { + mHash = IdenticonBase.getHash(input); + } else { + mHash = null; + } + // set up the cell colors according to the input that was provided via show(...) + setupColors(); + + // this view may now be drawn (and thus must be re-drawn) + mReady = true; + } + + public byte getByte(int index) { + if (mHash == null) { + return -128; + } else { + return mHash[index % mHash.length]; + } + } + + abstract protected int getRowCount(); + + abstract protected int getColumnCount(); + + abstract protected boolean isCellVisible(int row, int column); + + abstract protected int getIconColor(); + + public void updateSize(int w, int h) { + mCellWidth = w / mColumnCount; + mCellHeight = h / mRowCount; + } + + protected void draw(Canvas canvas) { + if (mReady) { + int x, y; + for (int r = 0; r < mRowCount; r++) { + for (int c = 0; c < mColumnCount; c++) { + x = mCellWidth * c; + y = mCellHeight * r; + + mPaint.setColor(mColors[r][c]); + + canvas.drawRect(x, y + mCellHeight, x + mCellWidth, y, mPaint); + } + } + } + } +} diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java new file mode 100644 index 000000000..19a5094b9 --- /dev/null +++ b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java @@ -0,0 +1,85 @@ +package im.delight.android.identicons; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.Log; + +/** + * Created by saiimons on 05/10/14. + */ +public class IdenticonDrawable extends Drawable { + private IdenticonBase mDelegate; + + private static final int CENTER_COLUMN_INDEX = 3; + + public IdenticonDrawable(String toShow) { + super(); + mDelegate = new IdenticonBase() { + @Override + protected int getRowCount() { + return 5; + } + + @Override + protected int getColumnCount() { + return 5; + } + + @Override + protected boolean isCellVisible(int row, int column) { + return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0; + } + + @Override + protected int getIconColor() { + return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128); + } + }; + mDelegate.show(toShow); + } + + @Override + public void setBounds(Rect bounds) { + super.setBounds(bounds); + Log.d("IDENTICON", "SIZE : " + (bounds.right - bounds.left) + " " + (bounds.bottom - bounds.top)); + mDelegate.updateSize(bounds.right - bounds.left, bounds.bottom - bounds.top); + } + + @Override + public void setBounds(int left, int top, int right, int bottom) { + super.setBounds(left, top, right, bottom); + mDelegate.updateSize(right - left, bottom - top); + } + + @Override + public void draw(Canvas canvas) { + Log.d("IDENTICON", "DRAW IN PROGRESS"); + mDelegate.draw(canvas); + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(ColorFilter cf) { + + } + + @Override + public int getOpacity() { + return 0; + } + + protected int getSymmetricColumnIndex(int row) { + if (row < CENTER_COLUMN_INDEX) { + return row; + } else { + return mDelegate.getColumnCount() - row - 1; + } + } +} diff --git a/briar-android/src/im/delight/android/identicons/IdenticonView.java b/briar-android/src/im/delight/android/identicons/IdenticonView.java new file mode 100644 index 000000000..061ba953c --- /dev/null +++ b/briar-android/src/im/delight/android/identicons/IdenticonView.java @@ -0,0 +1,118 @@ +package im.delight.android.identicons; + +/** + * Copyright 2014 www.delight.im + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.os.Build; +import android.util.AttributeSet; +import android.view.View; + +abstract public class IdenticonView extends View { + + + public IdenticonView(Context context) { + super(context); + init(); + } + + public IdenticonView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public IdenticonView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @SuppressLint("NewApi") + protected void init() { + setWillNotDraw(false); + if (Build.VERSION.SDK_INT >= 11) { + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + } + + public void show(String input) { + getDelegate().show(input); + invalidate(); + } + + public void show(int input) { + show(String.valueOf(input)); + } + + public void show(long input) { + show(String.valueOf(input)); + } + + public void show(float input) { + show(String.valueOf(input)); + } + + public void show(double input) { + show(String.valueOf(input)); + } + + public void show(byte input) { + show(String.valueOf(input)); + } + + public void show(char input) { + show(String.valueOf(input)); + } + + public void show(boolean input) { + show(String.valueOf(input)); + } + + public void show(Object input) { + if (input == null) { + getDelegate().show(null); + } else { + show(String.valueOf(input)); + } + } + + protected byte getByte(int index) { + return getDelegate().getByte(index); + } + + abstract protected IdenticonBase getDelegate(); + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + getDelegate().updateSize(w, h); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); + setMeasuredDimension(size, size); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + getDelegate().draw(canvas); + } + +} diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java new file mode 100644 index 000000000..170ed77ef --- /dev/null +++ b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java @@ -0,0 +1,81 @@ +package im.delight.android.identicons; + +/** + * Copyright 2014 www.delight.im + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; + +public class SymmetricIdenticon extends IdenticonView { + + private static final int CENTER_COLUMN_INDEX = 3; + + private IdenticonBase mDelegate; + + public SymmetricIdenticon(Context context) { + super(context); + initDelegate(); + } + + public SymmetricIdenticon(Context context, AttributeSet attrs) { + super(context, attrs); + initDelegate(); + } + + public SymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initDelegate(); + } + + private void initDelegate() { + mDelegate = new IdenticonBase() { + @Override + protected int getRowCount() { + return 5; + } + + @Override + protected int getColumnCount() { + return 5; + } + + @Override + protected boolean isCellVisible(int row, int column) { + return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0; + } + + @Override + protected int getIconColor() { + return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128); + } + }; + } + + @Override + protected IdenticonBase getDelegate() { + return mDelegate; + } + + protected int getSymmetricColumnIndex(int row) { + if (row < CENTER_COLUMN_INDEX) { + return row; + } else { + return getDelegate().getColumnCount() - row - 1; + } + } + +} From dfb9222ccda659ddeff472a4a21b64b4b6d2e412 Mon Sep 17 00:00:00 2001 From: str4d Date: Thu, 21 Jan 2016 02:36:21 +0000 Subject: [PATCH 2/9] Modify IdenticonBase to use Briar's hashing and to use byte[] instead of String --- .../identicons/AsymmetricIdenticon.java | 13 ++++++++++ .../android/identicons/IdenticonBase.java | 25 ++++++++----------- .../android/identicons/IdenticonDrawable.java | 9 ++++++- .../android/identicons/IdenticonView.java | 8 ++++-- .../identicons/SymmetricIdenticon.java | 13 ++++++++++ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java index bce32ff9e..b1d98d9b3 100644 --- a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java +++ b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java @@ -20,8 +20,15 @@ import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; +import org.briarproject.api.crypto.CryptoComponent; + +import javax.inject.Inject; + +import roboguice.RoboGuice; + public class AsymmetricIdenticon extends IdenticonView { + @Inject private CryptoComponent mCrypto; private IdenticonBase mDelegate; public AsymmetricIdenticon(Context context) { @@ -45,7 +52,13 @@ public class AsymmetricIdenticon extends IdenticonView { } private void initDelegate() { + RoboGuice.injectMembers(getContext(), this); mDelegate = new IdenticonBase() { + @Override + protected CryptoComponent getCrypto() { + return mCrypto; + } + @Override protected int getRowCount() { return 4; diff --git a/briar-android/src/im/delight/android/identicons/IdenticonBase.java b/briar-android/src/im/delight/android/identicons/IdenticonBase.java index a1a5d5dd3..8a7153ed9 100644 --- a/briar-android/src/im/delight/android/identicons/IdenticonBase.java +++ b/briar-android/src/im/delight/android/identicons/IdenticonBase.java @@ -4,15 +4,13 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import java.security.MessageDigest; +import org.briarproject.api.crypto.CryptoComponent; /** * Created by saiimons on 05/10/14. */ public abstract class IdenticonBase { - private static final String HASH_ALGORITHM = "SHA-256"; - - + private final CryptoComponent mCrypto; private final int mRowCount; private final int mColumnCount; private final Paint mPaint; @@ -23,6 +21,7 @@ public abstract class IdenticonBase { private volatile boolean mReady; public IdenticonBase() { + mCrypto = getCrypto(); mRowCount = getRowCount(); mColumnCount = getColumnCount(); mPaint = new Paint(); @@ -32,20 +31,16 @@ public abstract class IdenticonBase { mPaint.setDither(true); } - public static byte[] getHash(String input) { + public byte[] getHash(byte[] input) { byte[] mHash; // if the input was null if (input == null) { // we can't create a hash value and have nothing to show (draw to the view) mHash = null; - } - // if the input was a proper string (non-null) - else { - // generate a hash from the string to get unique but deterministic byte values + } else { + // generate a hash from the input to get unique but deterministic byte values try { - final MessageDigest digest = java.security.MessageDigest.getInstance(HASH_ALGORITHM); - digest.update(input == null ? new byte[0] : input.getBytes()); - mHash = digest.digest(); + mHash = mCrypto.hash(input); } catch (Exception e) { mHash = null; } @@ -68,9 +63,9 @@ public abstract class IdenticonBase { } } - public void show(String input) { + public void show(byte[] input) { if(input != null) { - mHash = IdenticonBase.getHash(input); + mHash = getHash(input); } else { mHash = null; } @@ -89,6 +84,8 @@ public abstract class IdenticonBase { } } + abstract protected CryptoComponent getCrypto(); + abstract protected int getRowCount(); abstract protected int getColumnCount(); diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java index 19a5094b9..4a5032428 100644 --- a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java +++ b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java @@ -7,6 +7,8 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.Log; +import org.briarproject.api.crypto.CryptoComponent; + /** * Created by saiimons on 05/10/14. */ @@ -15,9 +17,14 @@ public class IdenticonDrawable extends Drawable { private static final int CENTER_COLUMN_INDEX = 3; - public IdenticonDrawable(String toShow) { + public IdenticonDrawable(final CryptoComponent crypto, byte[] toShow) { super(); mDelegate = new IdenticonBase() { + @Override + protected CryptoComponent getCrypto() { + return crypto; + } + @Override protected int getRowCount() { return 5; diff --git a/briar-android/src/im/delight/android/identicons/IdenticonView.java b/briar-android/src/im/delight/android/identicons/IdenticonView.java index 061ba953c..32a4f863c 100644 --- a/briar-android/src/im/delight/android/identicons/IdenticonView.java +++ b/briar-android/src/im/delight/android/identicons/IdenticonView.java @@ -49,11 +49,15 @@ abstract public class IdenticonView extends View { } } - public void show(String input) { + public void show(byte[] input) { getDelegate().show(input); invalidate(); } + public void show(String input) { + show(input.getBytes()); + } + public void show(int input) { show(String.valueOf(input)); } @@ -71,7 +75,7 @@ abstract public class IdenticonView extends View { } public void show(byte input) { - show(String.valueOf(input)); + show(new byte[] { input }); } public void show(char input) { diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java index 170ed77ef..9a267a2f9 100644 --- a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java +++ b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java @@ -20,10 +20,17 @@ import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; +import org.briarproject.api.crypto.CryptoComponent; + +import javax.inject.Inject; + +import roboguice.RoboGuice; + public class SymmetricIdenticon extends IdenticonView { private static final int CENTER_COLUMN_INDEX = 3; + @Inject private CryptoComponent mCrypto; private IdenticonBase mDelegate; public SymmetricIdenticon(Context context) { @@ -42,7 +49,13 @@ public class SymmetricIdenticon extends IdenticonView { } private void initDelegate() { + RoboGuice.injectMembers(getContext(), this); mDelegate = new IdenticonBase() { + @Override + protected CryptoComponent getCrypto() { + return mCrypto; + } + @Override protected int getRowCount() { return 5; From c7387ee37c5d2f362bd8b471c2e59997e4ceefec Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 26 Jan 2016 02:44:23 +0000 Subject: [PATCH 3/9] Modify IdenticonBase to use a dark background for light identicons --- .../im/delight/android/identicons/IdenticonBase.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/briar-android/src/im/delight/android/identicons/IdenticonBase.java b/briar-android/src/im/delight/android/identicons/IdenticonBase.java index 8a7153ed9..f5ccc90e4 100644 --- a/briar-android/src/im/delight/android/identicons/IdenticonBase.java +++ b/briar-android/src/im/delight/android/identicons/IdenticonBase.java @@ -51,13 +51,14 @@ public abstract class IdenticonBase { protected void setupColors() { mColors = new int[mRowCount][mColumnCount]; int colorVisible = getIconColor(); + int colorInvisible = getBackgroundColor(); for (int r = 0; r < mRowCount; r++) { for (int c = 0; c < mColumnCount; c++) { if (isCellVisible(r, c)) { mColors[r][c] = colorVisible; } else { - mColors[r][c] = Color.TRANSPARENT; + mColors[r][c] = colorInvisible; } } } @@ -94,6 +95,15 @@ public abstract class IdenticonBase { abstract protected int getIconColor(); + protected int getBackgroundColor() { + float[] hsv = new float[3]; + Color.colorToHSV(getIconColor(), hsv); + if (hsv[2] < 0.5) + return Color.parseColor("#ffeeeeee"); // @color/background_material_light + else + return Color.parseColor("#ff303030"); // @color/background_material_dark + } + public void updateSize(int w, int h) { mCellWidth = w / mColumnCount; mCellHeight = h / mRowCount; From e62d60ff524b715f7de91b762695160ff886d1f6 Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 5 Jan 2016 06:10:36 +0000 Subject: [PATCH 4/9] Add identicons to contact list --- .../res/layout/list_item_contact.xml | 94 ++++++++++++------- briar-android/res/values/dimens.xml | 6 ++ .../android/contact/ContactListAdapter.java | 9 +- 3 files changed, 72 insertions(+), 37 deletions(-) diff --git a/briar-android/res/layout/list_item_contact.xml b/briar-android/res/layout/list_item_contact.xml index 69ec0383e..0fc6d195f 100644 --- a/briar-android/res/layout/list_item_contact.xml +++ b/briar-android/res/layout/list_item_contact.xml @@ -2,49 +2,71 @@ + android:layout_height="wrap_content" + android:orientation="vertical"> - + android:layout_height="@dimen/listitem_height_one_line_avatar" + android:background="?attr/selectableItemBackground"> - + - + - + - + + + + + + + diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml index e417b0897..181b5b992 100644 --- a/briar-android/res/values/dimens.xml +++ b/briar-android/res/values/dimens.xml @@ -20,4 +20,10 @@ 300dp 1dp + 16dp + 40dp + 72dp + + 56dp + diff --git a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java index 9d040e87d..ac83a2fb4 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java @@ -14,10 +14,13 @@ import android.widget.TextView; import org.briarproject.R; import org.briarproject.api.contact.ContactId; +import org.briarproject.api.identity.Author; import org.briarproject.api.sync.GroupId; import java.util.List; +import im.delight.android.identicons.IdenticonView; + import static android.support.v7.util.SortedList.INVALID_POSITION; public class ContactListAdapter @@ -113,7 +116,9 @@ public class ContactListAdapter ui.bulb.setImageResource(R.drawable.contact_disconnected); } - String contactName = item.getContact().getAuthor().getName(); + Author author = item.getContact().getAuthor(); + ui.identicon.show(author.getId().getBytes()); + String contactName = author.getName(); if (unread > 0) { ui.name.setText(contactName + " (" + unread + ")"); } else { @@ -193,6 +198,7 @@ public class ContactListAdapter public static class ContactHolder extends RecyclerView.ViewHolder { public ViewGroup layout; public ImageView bulb; + public IdenticonView identicon; public TextView name; public TextView date; @@ -201,6 +207,7 @@ public class ContactListAdapter layout = (ViewGroup) v; bulb = (ImageView) v.findViewById(R.id.bulbView); + identicon = (IdenticonView) v.findViewById(R.id.identiconView); name = (TextView) v.findViewById(R.id.nameView); date = (TextView) v.findViewById(R.id.dateView); } From 88d81634ca42be1866ecc09ac410eb5bcc84b331 Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 5 Jan 2016 06:11:20 +0000 Subject: [PATCH 5/9] Add identicons to conversations --- briar-android/res/layout/list_item_msg_in.xml | 10 +++++- .../android/contact/ConversationActivity.java | 3 ++ .../android/contact/ConversationAdapter.java | 35 +++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/briar-android/res/layout/list_item_msg_in.xml b/briar-android/res/layout/list_item_msg_in.xml index d93d269e7..614484e51 100644 --- a/briar-android/res/layout/list_item_msg_in.xml +++ b/briar-android/res/layout/list_item_msg_in.xml @@ -4,12 +4,20 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical" + android:orientation="horizontal" android:paddingRight="@dimen/margin_medium" android:paddingEnd="@dimen/margin_medium" android:paddingTop="@dimen/margin_small" android:paddingBottom="@dimen/margin_small"> + + Date: Tue, 5 Jan 2016 07:19:10 +0000 Subject: [PATCH 6/9] Migrate AuthorView to XML, add identicon --- briar-android/res/layout/author_view.xml | 42 ++++++++++++ .../android/forum/ForumActivity.java | 6 +- .../android/forum/ForumAdapter.java | 3 +- .../android/forum/ReadForumPostActivity.java | 15 ++-- .../briarproject/android/util/AuthorView.java | 68 ++++++++++++------- 5 files changed, 100 insertions(+), 34 deletions(-) create mode 100644 briar-android/res/layout/author_view.xml diff --git a/briar-android/res/layout/author_view.xml b/briar-android/res/layout/author_view.xml new file mode 100644 index 000000000..a3e473dc7 --- /dev/null +++ b/briar-android/res/layout/author_view.xml @@ -0,0 +1,42 @@ + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java index 7f725d40d..a67ebd12e 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java +++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java @@ -18,6 +18,7 @@ import org.briarproject.android.util.ElasticHorizontalSpace; import org.briarproject.android.util.HorizontalBorder; import org.briarproject.android.util.ListLoadingProgressBar; import org.briarproject.api.android.AndroidNotificationManager; +import org.briarproject.api.android.ReferenceManager; import org.briarproject.api.db.DbException; import org.briarproject.api.db.NoSuchMessageException; import org.briarproject.api.db.NoSuchSubscriptionException; @@ -70,6 +71,8 @@ public class ForumActivity extends BriarActivity implements EventListener, private ListLoadingProgressBar loading = null; private ImageButton composeButton = null, shareButton = null; + @Inject private ReferenceManager referenceManager; + // Fields that are accessed from background threads must be volatile @Inject private volatile ForumManager forumManager; @Inject private volatile EventBus eventBus; @@ -366,7 +369,8 @@ public class ForumActivity extends BriarActivity implements EventListener, i.putExtra("briar.FORUM_NAME", forum.getName()); i.putExtra("briar.MESSAGE_ID", header.getId().getBytes()); Author author = header.getAuthor(); - if (author != null) i.putExtra("briar.AUTHOR_NAME", author.getName()); + if (author != null) i.putExtra("briar.AUTHOR_HANDLE", + referenceManager.putReference(author, Author.class)); i.putExtra("briar.AUTHOR_STATUS", header.getAuthorStatus().name()); i.putExtra("briar.CONTENT_TYPE", header.getContentType()); i.putExtra("briar.TIMESTAMP", header.getTimestamp()); diff --git a/briar-android/src/org/briarproject/android/forum/ForumAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumAdapter.java index ac1211447..30ff7d0bf 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumAdapter.java +++ b/briar-android/src/org/briarproject/android/forum/ForumAdapter.java @@ -55,8 +55,7 @@ class ForumAdapter extends ArrayAdapter { AuthorView authorView = new AuthorView(ctx); authorView.setLayoutParams(WRAP_WRAP_1); Author author = header.getAuthor(); - if (author == null) authorView.init(null, header.getAuthorStatus()); - else authorView.init(author.getName(), header.getAuthorStatus()); + authorView.init(author, header.getAuthorStatus()); headerLayout.addView(authorView); TextView date = new TextView(ctx); diff --git a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java index 706cb31fe..5ffc8aaa8 100644 --- a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java +++ b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java @@ -17,6 +17,7 @@ import org.briarproject.android.util.AuthorView; import org.briarproject.android.util.ElasticHorizontalSpace; import org.briarproject.android.util.HorizontalBorder; import org.briarproject.android.util.LayoutUtils; +import org.briarproject.api.android.ReferenceManager; import org.briarproject.api.db.DbException; import org.briarproject.api.db.NoSuchMessageException; import org.briarproject.api.forum.ForumManager; @@ -56,6 +57,8 @@ implements OnClickListener { private TextView content = null; private int position = -1; + @Inject private ReferenceManager referenceManager; + // Fields that are accessed from background threads must be volatile @Inject private volatile ForumManager forumManager; private volatile MessageId messageId = null; @@ -82,7 +85,9 @@ implements OnClickListener { if (minTimestamp == -1) throw new IllegalStateException(); position = i.getIntExtra("briar.POSITION", -1); if (position == -1) throw new IllegalStateException(); - String authorName = i.getStringExtra("briar.AUTHOR_NAME"); + long authorHandle = i.getLongExtra("briar.AUTHOR_HANDLE", -1); + if (authorHandle == -1) throw new IllegalStateException(); + Author author = referenceManager.removeReference(authorHandle, Author.class); String s = i.getStringExtra("briar.AUTHOR_STATUS"); if (s == null) throw new IllegalStateException(); Author.Status authorStatus = Author.Status.valueOf(s); @@ -102,10 +107,10 @@ implements OnClickListener { header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); - AuthorView author = new AuthorView(this); - author.setLayoutParams(WRAP_WRAP_1); - author.init(authorName, authorStatus); - header.addView(author); + AuthorView authorView = new AuthorView(this); + authorView.setLayoutParams(WRAP_WRAP_1); + authorView.init(author, authorStatus); + header.addView(authorView); int pad = LayoutUtils.getPadding(this); diff --git a/briar-android/src/org/briarproject/android/util/AuthorView.java b/briar-android/src/org/briarproject/android/util/AuthorView.java index 152a801b9..166e8d63b 100644 --- a/briar-android/src/org/briarproject/android/util/AuthorView.java +++ b/briar-android/src/org/briarproject/android/util/AuthorView.java @@ -1,42 +1,62 @@ package org.briarproject.android.util; import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.TextView; import org.briarproject.R; import org.briarproject.api.identity.Author; -import static android.text.TextUtils.TruncateAt.END; +import im.delight.android.identicons.IdenticonView; -public class AuthorView extends RelativeLayout { +public class AuthorView extends FrameLayout { + + private IdenticonView identiconView; + private TextView nameView; + private ImageView statusView; public AuthorView(Context ctx) { super(ctx); + + initViews(); } - public void init(String name, Author.Status status) { - Context ctx = getContext(); - int pad = LayoutUtils.getPadding(ctx); + public AuthorView(Context context, AttributeSet attrs) { + super(context, attrs); - TextView nameView = new TextView(ctx); - nameView.setId(1); - nameView.setTextSize(18); - nameView.setSingleLine(); - nameView.setEllipsize(END); - nameView.setPadding(pad, pad, pad, pad); - if (name == null) nameView.setText(R.string.anonymous); - else nameView.setText(name); - LayoutParams leftOf = CommonLayoutParams.relative(); - leftOf.addRule(ALIGN_PARENT_LEFT); - leftOf.addRule(CENTER_VERTICAL); - leftOf.addRule(LEFT_OF, 2); - addView(nameView, leftOf); + initViews(); + } + + public AuthorView(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + + initViews(); + } + + private void initViews() { + if (isInEditMode()) + return; + + View v = LayoutInflater.from(getContext()).inflate( + R.layout.author_view, this, true); + + identiconView = (IdenticonView) v.findViewById(R.id.identiconView); + nameView = (TextView) v.findViewById(R.id.nameView); + statusView = (ImageView) v.findViewById(R.id.statusView); + } + + public void init(Author author, Author.Status status) { + if (author == null) nameView.setText(R.string.anonymous); + else { + identiconView.show(author.getId().getBytes()); + nameView.setText(author.getName()); + } - ImageView statusView = new ImageView(ctx); - statusView.setId(2); - statusView.setPadding(0, pad, pad, pad); switch(status) { case ANONYMOUS: statusView.setImageResource(R.drawable.identity_anonymous); @@ -51,9 +71,5 @@ public class AuthorView extends RelativeLayout { statusView.setImageResource(R.drawable.identity_verified); break; } - LayoutParams right = CommonLayoutParams.relative(); - right.addRule(ALIGN_PARENT_RIGHT); - right.addRule(CENTER_VERTICAL); - addView(statusView, right); } } From 9318a50cb708a2b5186e3df1544c95149e167deb Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 26 Jan 2016 03:39:30 +0000 Subject: [PATCH 7/9] Migrate LocalAuthorSpinnerAdapter to XML, add identicons --- briar-android/res/layout/dropdown_author.xml | 25 ++++++++++ briar-android/res/values/dimens.xml | 2 + .../identity/LocalAuthorSpinnerAdapter.java | 50 +++++++++++-------- 3 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 briar-android/res/layout/dropdown_author.xml diff --git a/briar-android/res/layout/dropdown_author.xml b/briar-android/res/layout/dropdown_author.xml new file mode 100644 index 000000000..461268243 --- /dev/null +++ b/briar-android/res/layout/dropdown_author.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml index 181b5b992..8c11314ab 100644 --- a/briar-android/res/values/dimens.xml +++ b/briar-android/res/values/dimens.xml @@ -26,4 +26,6 @@ 56dp + 32dp + diff --git a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java index 2aa2358f4..8e774ceb7 100644 --- a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java +++ b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java @@ -1,6 +1,7 @@ package org.briarproject.android.identity; import android.content.Context; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; @@ -8,14 +9,14 @@ import android.widget.SpinnerAdapter; import android.widget.TextView; import org.briarproject.R; -import org.briarproject.android.util.LayoutUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import static android.text.TextUtils.TruncateAt.END; +import im.delight.android.identicons.IdenticonView; + import static org.briarproject.android.identity.LocalAuthorItem.ANONYMOUS; import static org.briarproject.android.identity.LocalAuthorItem.NEW; @@ -49,17 +50,32 @@ implements SpinnerAdapter { @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { - TextView name = new TextView(ctx); - name.setTextSize(18); - name.setSingleLine(); - name.setEllipsize(END); - int pad = LayoutUtils.getPadding(ctx); - name.setPadding(pad, pad, pad, pad); + View view; + if (convertView == null) { + LayoutInflater inflater = + (LayoutInflater) ctx + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.dropdown_author, parent, false); + } else + view = convertView; + + TextView name = (TextView) view.findViewById(R.id.nameView); + IdenticonView identicon = + (IdenticonView) view.findViewById(R.id.identiconView); + LocalAuthorItem item = getItem(position); - if (item == ANONYMOUS) name.setText(R.string.anonymous); - else if (item == NEW) name.setText(R.string.new_identity_item); - else name.setText(item.getLocalAuthor().getName()); - return name; + if (item == ANONYMOUS) { + name.setText(R.string.anonymous); + identicon.setVisibility(View.INVISIBLE); + } else if (item == NEW) { + name.setText(R.string.new_identity_item); + identicon.setVisibility(View.INVISIBLE); + } else { + name.setText(item.getLocalAuthor().getName()); + identicon.setVisibility(View.VISIBLE); + identicon.show(item.getLocalAuthor().getId().getBytes()); + } + return view; } public LocalAuthorItem getItem(int position) { @@ -78,15 +94,7 @@ implements SpinnerAdapter { } public View getView(int position, View convertView, ViewGroup parent) { - TextView name = new TextView(ctx); - name.setTextSize(18); - name.setSingleLine(); - name.setEllipsize(END); - LocalAuthorItem item = getItem(position); - if (item == ANONYMOUS) name.setText(R.string.anonymous); - else if (item == NEW) name.setText(R.string.new_identity_item); - else name.setText(item.getLocalAuthor().getName()); - return name; + return getDropDownView(position, convertView, parent); } @Override From 9749eefb90ecca7cc152dc3459c0231129b64415 Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 26 Jan 2016 19:36:21 +0000 Subject: [PATCH 8/9] Make symmetric identicons 9x9 instead of 5x5 --- .../im/delight/android/identicons/IdenticonDrawable.java | 6 +++--- .../im/delight/android/identicons/SymmetricIdenticon.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java index 4a5032428..ed9b0de2f 100644 --- a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java +++ b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java @@ -15,7 +15,7 @@ import org.briarproject.api.crypto.CryptoComponent; public class IdenticonDrawable extends Drawable { private IdenticonBase mDelegate; - private static final int CENTER_COLUMN_INDEX = 3; + private static final int CENTER_COLUMN_INDEX = 5; public IdenticonDrawable(final CryptoComponent crypto, byte[] toShow) { super(); @@ -27,12 +27,12 @@ public class IdenticonDrawable extends Drawable { @Override protected int getRowCount() { - return 5; + return 9; } @Override protected int getColumnCount() { - return 5; + return 9; } @Override diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java index 9a267a2f9..f102e45f4 100644 --- a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java +++ b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java @@ -28,7 +28,7 @@ import roboguice.RoboGuice; public class SymmetricIdenticon extends IdenticonView { - private static final int CENTER_COLUMN_INDEX = 3; + private static final int CENTER_COLUMN_INDEX = 5; @Inject private CryptoComponent mCrypto; private IdenticonBase mDelegate; @@ -58,12 +58,12 @@ public class SymmetricIdenticon extends IdenticonView { @Override protected int getRowCount() { - return 5; + return 9; } @Override protected int getColumnCount() { - return 5; + return 9; } @Override From 90eded1421ce0fb595e8bd18c227bee6be9a6db0 Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 26 Jan 2016 20:21:35 +0000 Subject: [PATCH 9/9] Make identicons round This commit renames identicons to avatars in field names, and uses an ImageView derivative to show the identicons, which should make implementing #214 easier. --- briar-android/build.gradle | 1 + briar-android/res/layout/author_view.xml | 4 ++-- briar-android/res/layout/dropdown_author.xml | 4 ++-- .../res/layout/list_item_contact.xml | 4 ++-- briar-android/res/layout/list_item_msg_in.xml | 4 ++-- .../android/identicons/IdenticonDrawable.java | 10 +++++++++ .../android/contact/ContactListAdapter.java | 14 +++++++----- .../android/contact/ContactListFragment.java | 5 ++++- .../android/contact/ConversationActivity.java | 4 +++- .../android/contact/ConversationAdapter.java | 14 +++++++----- .../android/forum/WriteForumPostActivity.java | 2 +- .../identity/LocalAuthorSpinnerAdapter.java | 22 ++++++++++++------- .../invitation/ChooseIdentityView.java | 9 +++++++- .../briarproject/android/util/AuthorView.java | 15 +++++++++---- 14 files changed, 78 insertions(+), 34 deletions(-) diff --git a/briar-android/build.gradle b/briar-android/build.gradle index f982a86be..4ead68e29 100644 --- a/briar-android/build.gradle +++ b/briar-android/build.gradle @@ -17,6 +17,7 @@ dependencies { compile "org.roboguice:roboguice:2.0" compile "info.guardianproject.panic:panic:0.5" compile "info.guardianproject.trustedintents:trustedintents:0.2" + compile "de.hdodenhof:circleimageview:2.0.0" } dependencyVerification { diff --git a/briar-android/res/layout/author_view.xml b/briar-android/res/layout/author_view.xml index a3e473dc7..92c863c37 100644 --- a/briar-android/res/layout/author_view.xml +++ b/briar-android/res/layout/author_view.xml @@ -4,8 +4,8 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - diff --git a/briar-android/res/layout/list_item_contact.xml b/briar-android/res/layout/list_item_contact.xml index 0fc6d195f..8259e1b3b 100644 --- a/briar-android/res/layout/list_item_contact.xml +++ b/briar-android/res/layout/list_item_contact.xml @@ -11,8 +11,8 @@ android:layout_height="@dimen/listitem_height_one_line_avatar" android:background="?attr/selectableItemBackground"> - - 0) { ui.name.setText(contactName + " (" + unread + ")"); @@ -198,7 +202,7 @@ public class ContactListAdapter public static class ContactHolder extends RecyclerView.ViewHolder { public ViewGroup layout; public ImageView bulb; - public IdenticonView identicon; + public ImageView avatar; public TextView name; public TextView date; @@ -207,7 +211,7 @@ public class ContactListAdapter layout = (ViewGroup) v; bulb = (ImageView) v.findViewById(R.id.bulbView); - identicon = (IdenticonView) v.findViewById(R.id.identiconView); + avatar = (ImageView) v.findViewById(R.id.avatarView); name = (TextView) v.findViewById(R.id.nameView); date = (TextView) v.findViewById(R.id.dateView); } diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java index d2bff01e5..bd52792c5 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java @@ -16,6 +16,7 @@ import org.briarproject.android.util.BriarRecyclerView; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; +import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.NoSuchContactException; import org.briarproject.api.event.ContactAddedEvent; @@ -62,6 +63,8 @@ public class ContactListFragment extends BaseEventFragment { return TAG; } + @Inject + private CryptoComponent crypto; @Inject private ConnectionRegistry connectionRegistry; private ContactListAdapter adapter = null; @@ -83,7 +86,7 @@ public class ContactListFragment extends BaseEventFragment { inflater.inflate(R.layout.activity_contact_list, container, false); - adapter = new ContactListAdapter(getContext()); + adapter = new ContactListAdapter(getContext(), crypto); list = (BriarRecyclerView) contentView.findViewById(R.id.contactList); list.setLayoutManager(new LinearLayoutManager(getContext())); list.setAdapter(adapter); diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index 732d64653..dc96bd47f 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -23,6 +23,7 @@ import org.briarproject.api.android.AndroidNotificationManager; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; +import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoExecutor; import org.briarproject.api.db.DbException; import org.briarproject.api.db.NoSuchContactException; @@ -71,6 +72,7 @@ public class ConversationActivity extends BriarActivity private static final Logger LOG = Logger.getLogger(ConversationActivity.class.getName()); + @Inject private CryptoComponent crypto; @Inject private AndroidNotificationManager notificationManager; @Inject private ConnectionRegistry connectionRegistry; @Inject @CryptoExecutor private Executor cryptoExecutor; @@ -102,7 +104,7 @@ public class ConversationActivity extends BriarActivity setContentView(R.layout.activity_conversation); - adapter = new ConversationAdapter(this); + adapter = new ConversationAdapter(this, crypto); list = (BriarRecyclerView) findViewById(R.id.conversationView); list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java index a1cf4d013..a35db98bd 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java @@ -11,10 +11,11 @@ import android.widget.ImageView; import android.widget.TextView; import org.briarproject.R; +import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.util.StringUtils; -import im.delight.android.identicons.IdenticonView; +import im.delight.android.identicons.IdenticonDrawable; import static android.support.v7.util.SortedList.INVALID_POSITION; @@ -72,10 +73,12 @@ class ConversationAdapter extends } }); private Context ctx; + private CryptoComponent crypto; private byte[] identiconKey; - public ConversationAdapter(Context context) { + public ConversationAdapter(Context context, CryptoComponent cryptoComponent) { ctx = context; + crypto = cryptoComponent; } public void setIdenticonKey(byte[] key) { @@ -129,7 +132,8 @@ class ConversationAdapter extends } } else { if (identiconKey != null) - ui.identicon.show(identiconKey); + ui.avatar.setImageDrawable( + new IdenticonDrawable(crypto, identiconKey)); if (!header.isRead()) { int left = ui.layout.getPaddingLeft(); int top = ui.layout.getPaddingTop(); @@ -198,7 +202,7 @@ class ConversationAdapter extends public TextView body; public TextView date; public ImageView status; - public IdenticonView identicon; + public ImageView avatar; public MessageHolder(View v, int type) { super(v); @@ -211,7 +215,7 @@ class ConversationAdapter extends if (type == MSG_OUT) { status = (ImageView) v.findViewById(R.id.msgStatus); } else { - identicon = (IdenticonView) v.findViewById(R.id.msgIdenticon); + avatar = (ImageView) v.findViewById(R.id.msgAvatar); } } } diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java index 40e72a148..a38433f31 100644 --- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java +++ b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java @@ -123,7 +123,7 @@ implements OnItemSelectedListener, OnClickListener { left.addRule(CENTER_VERTICAL); header.addView(from, left); - adapter = new LocalAuthorSpinnerAdapter(this, true); + adapter = new LocalAuthorSpinnerAdapter(this, crypto, true); spinner = new Spinner(this); spinner.setId(2); spinner.setAdapter(adapter); diff --git a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java index 8e774ceb7..a0e2d88de 100644 --- a/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java +++ b/briar-android/src/org/briarproject/android/identity/LocalAuthorSpinnerAdapter.java @@ -5,17 +5,19 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.ImageView; import android.widget.SpinnerAdapter; import android.widget.TextView; import org.briarproject.R; +import org.briarproject.api.crypto.CryptoComponent; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import im.delight.android.identicons.IdenticonView; +import im.delight.android.identicons.IdenticonDrawable; import static org.briarproject.android.identity.LocalAuthorItem.ANONYMOUS; import static org.briarproject.android.identity.LocalAuthorItem.NEW; @@ -24,11 +26,14 @@ public class LocalAuthorSpinnerAdapter extends BaseAdapter implements SpinnerAdapter { private final Context ctx; + private final CryptoComponent crypto; private final boolean includeAnonymous; private final List list = new ArrayList(); - public LocalAuthorSpinnerAdapter(Context ctx, boolean includeAnonymous) { + public LocalAuthorSpinnerAdapter(Context ctx, + CryptoComponent crypto, boolean includeAnonymous) { this.ctx = ctx; + this.crypto = crypto; this.includeAnonymous = includeAnonymous; } @@ -60,20 +65,21 @@ implements SpinnerAdapter { view = convertView; TextView name = (TextView) view.findViewById(R.id.nameView); - IdenticonView identicon = - (IdenticonView) view.findViewById(R.id.identiconView); + ImageView avatar = + (ImageView) view.findViewById(R.id.avatarView); LocalAuthorItem item = getItem(position); if (item == ANONYMOUS) { name.setText(R.string.anonymous); - identicon.setVisibility(View.INVISIBLE); + avatar.setVisibility(View.INVISIBLE); } else if (item == NEW) { name.setText(R.string.new_identity_item); - identicon.setVisibility(View.INVISIBLE); + avatar.setVisibility(View.INVISIBLE); } else { name.setText(item.getLocalAuthor().getName()); - identicon.setVisibility(View.VISIBLE); - identicon.show(item.getLocalAuthor().getId().getBytes()); + avatar.setVisibility(View.VISIBLE); + avatar.setImageDrawable(new IdenticonDrawable(crypto, + item.getLocalAuthor().getId().getBytes())); } return view; } diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java index 940de7e75..912d28cce 100644 --- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java +++ b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java @@ -16,11 +16,16 @@ import org.briarproject.android.identity.CreateIdentityActivity; import org.briarproject.android.identity.LocalAuthorItem; import org.briarproject.android.identity.LocalAuthorItemComparator; import org.briarproject.android.identity.LocalAuthorSpinnerAdapter; +import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.LocalAuthor; import java.util.Collection; +import javax.inject.Inject; + +import roboguice.RoboGuice; + import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION; import static org.briarproject.android.identity.LocalAuthorItem.NEW; @@ -30,6 +35,7 @@ import static org.briarproject.android.invitation.AddContactActivity.REQUEST_CRE class ChooseIdentityView extends AddContactView implements OnItemSelectedListener, OnClickListener { + @Inject private CryptoComponent crypto; private LocalAuthorSpinnerAdapter adapter = null; private Spinner spinner = null; @@ -40,6 +46,7 @@ implements OnItemSelectedListener, OnClickListener { void populate() { removeAllViews(); Context ctx = getContext(); + RoboGuice.injectMembers(ctx, this); LayoutInflater inflater = (LayoutInflater) ctx.getSystemService (Context.LAYOUT_INFLATER_SERVICE); @@ -50,7 +57,7 @@ implements OnItemSelectedListener, OnClickListener { TextView step = (TextView) view.findViewById(R.id.stepView); step.setText(String.format(ctx.getString(R.string.step), 1, 3)); - adapter = new LocalAuthorSpinnerAdapter(ctx, false); + adapter = new LocalAuthorSpinnerAdapter(ctx, crypto, false); spinner = (Spinner) view.findViewById(R.id.spinner); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); diff --git a/briar-android/src/org/briarproject/android/util/AuthorView.java b/briar-android/src/org/briarproject/android/util/AuthorView.java index 166e8d63b..dd20a28e7 100644 --- a/briar-android/src/org/briarproject/android/util/AuthorView.java +++ b/briar-android/src/org/briarproject/android/util/AuthorView.java @@ -9,13 +9,18 @@ import android.widget.ImageView; import android.widget.TextView; import org.briarproject.R; +import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.identity.Author; -import im.delight.android.identicons.IdenticonView; +import javax.inject.Inject; + +import im.delight.android.identicons.IdenticonDrawable; +import roboguice.RoboGuice; public class AuthorView extends FrameLayout { - private IdenticonView identiconView; + @Inject private CryptoComponent crypto; + private ImageView avatarView; private TextView nameView; private ImageView statusView; @@ -39,13 +44,14 @@ public class AuthorView extends FrameLayout { } private void initViews() { + RoboGuice.injectMembers(getContext(), this); if (isInEditMode()) return; View v = LayoutInflater.from(getContext()).inflate( R.layout.author_view, this, true); - identiconView = (IdenticonView) v.findViewById(R.id.identiconView); + avatarView = (ImageView) v.findViewById(R.id.avatarView); nameView = (TextView) v.findViewById(R.id.nameView); statusView = (ImageView) v.findViewById(R.id.statusView); } @@ -53,7 +59,8 @@ public class AuthorView extends FrameLayout { public void init(Author author, Author.Status status) { if (author == null) nameView.setText(R.string.anonymous); else { - identiconView.show(author.getId().getBytes()); + avatarView.setImageDrawable( + new IdenticonDrawable(crypto, author.getId().getBytes())); nameView.setText(author.getName()); }