Migrate avatars to use recipientId filenames.
This commit is contained in:
parent
b7ce220600
commit
b89163bb14
17 changed files with 315 additions and 62 deletions
|
@ -41,6 +41,7 @@ message Sticker {
|
||||||
|
|
||||||
message Avatar {
|
message Avatar {
|
||||||
optional string name = 1;
|
optional string name = 1;
|
||||||
|
optional string recipientId = 3;
|
||||||
optional uint32 length = 2;
|
optional uint32 length = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||||
Drawable fallback = new GeneratedContactPhoto(name, R.drawable.ic_profile_default).asDrawable(this, fallbackColor.toAvatarColor(this));
|
Drawable fallback = new GeneratedContactPhoto(name, R.drawable.ic_profile_default).asDrawable(this, fallbackColor.toAvatarColor(this));
|
||||||
|
|
||||||
GlideApp.with(this)
|
GlideApp.with(this)
|
||||||
.load(new ProfileContactPhoto(recipient.requireAddress(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this))))
|
.load(new ProfileContactPhoto(recipient.getId(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this))))
|
||||||
.error(fallback)
|
.error(fallback)
|
||||||
.circleCrop()
|
.circleCrop()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||||
import org.thoughtcrime.securesms.profiles.SystemProfileUtil;
|
import org.thoughtcrime.securesms.profiles.SystemProfileUtil;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
|
@ -263,14 +264,14 @@ public class CreateProfileActivity extends BaseActionBarActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeProfileAvatar(boolean excludeSystem) {
|
private void initializeProfileAvatar(boolean excludeSystem) {
|
||||||
Address ourAddress = Address.fromSerialized(TextSecurePreferences.getLocalNumber(this));
|
RecipientId selfId = Recipient.self().getId();
|
||||||
|
|
||||||
if (AvatarHelper.getAvatarFile(this, ourAddress).exists() && AvatarHelper.getAvatarFile(this, ourAddress).length() > 0) {
|
if (AvatarHelper.getAvatarFile(this, selfId).exists() && AvatarHelper.getAvatarFile(this, selfId).length() > 0) {
|
||||||
new AsyncTask<Void, Void, byte[]>() {
|
new AsyncTask<Void, Void, byte[]>() {
|
||||||
@Override
|
@Override
|
||||||
protected byte[] doInBackground(Void... params) {
|
protected byte[] doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
return Util.readFully(AvatarHelper.getInputStreamFor(CreateProfileActivity.this, ourAddress));
|
return Util.readFully(AvatarHelper.getInputStreamFor(CreateProfileActivity.this, selfId));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -373,7 +374,7 @@ public class CreateProfileActivity extends BaseActionBarActivity {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
accountManager.setProfileAvatar(profileKey, avatar);
|
accountManager.setProfileAvatar(profileKey, avatar);
|
||||||
AvatarHelper.setAvatar(CreateProfileActivity.this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), avatarBytes);
|
AvatarHelper.setAvatar(CreateProfileActivity.this, Recipient.self().getId(), avatarBytes);
|
||||||
TextSecurePreferences.setProfileAvatarId(CreateProfileActivity.this, new SecureRandom().nextInt());
|
TextSecurePreferences.setProfileAvatarId(CreateProfileActivity.this, new SecureRandom().nextInt());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
|
|
|
@ -206,7 +206,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHeader(@NonNull Recipient recipient) {
|
private void setHeader(@NonNull Recipient recipient) {
|
||||||
ContactPhoto contactPhoto = recipient.isLocalNumber() ? new ProfileContactPhoto(recipient.requireAddress(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this)))
|
ContactPhoto contactPhoto = recipient.isLocalNumber() ? new ProfileContactPhoto(recipient.getId(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this)))
|
||||||
: recipient.getContactPhoto();
|
: recipient.getContactPhoto();
|
||||||
FallbackContactPhoto fallbackPhoto = recipient.isLocalNumber() ? new ResourceContactPhoto(R.drawable.ic_profile_default, R.drawable.ic_person_large)
|
FallbackContactPhoto fallbackPhoto = recipient.isLocalNumber() ? new ResourceContactPhoto(R.drawable.ic_profile_default, R.drawable.ic_person_large)
|
||||||
: recipient.getFallbackContactPhoto();
|
: recipient.getFallbackContactPhoto();
|
||||||
|
|
|
@ -3475,6 +3475,21 @@ public final class BackupProtos {
|
||||||
com.google.protobuf.ByteString
|
com.google.protobuf.ByteString
|
||||||
getNameBytes();
|
getNameBytes();
|
||||||
|
|
||||||
|
// optional string recipientId = 3;
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
boolean hasRecipientId();
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
java.lang.String getRecipientId();
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
com.google.protobuf.ByteString
|
||||||
|
getRecipientIdBytes();
|
||||||
|
|
||||||
// optional uint32 length = 2;
|
// optional uint32 length = 2;
|
||||||
/**
|
/**
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
|
@ -3542,10 +3557,15 @@ public final class BackupProtos {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 16: {
|
case 16: {
|
||||||
bitField0_ |= 0x00000002;
|
bitField0_ |= 0x00000004;
|
||||||
length_ = input.readUInt32();
|
length_ = input.readUInt32();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 26: {
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
recipientId_ = input.readBytes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||||
|
@ -3629,6 +3649,49 @@ public final class BackupProtos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// optional string recipientId = 3;
|
||||||
|
public static final int RECIPIENTID_FIELD_NUMBER = 3;
|
||||||
|
private java.lang.Object recipientId_;
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasRecipientId() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getRecipientId() {
|
||||||
|
java.lang.Object ref = recipientId_;
|
||||||
|
if (ref instanceof java.lang.String) {
|
||||||
|
return (java.lang.String) ref;
|
||||||
|
} else {
|
||||||
|
com.google.protobuf.ByteString bs =
|
||||||
|
(com.google.protobuf.ByteString) ref;
|
||||||
|
java.lang.String s = bs.toStringUtf8();
|
||||||
|
if (bs.isValidUtf8()) {
|
||||||
|
recipientId_ = s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getRecipientIdBytes() {
|
||||||
|
java.lang.Object ref = recipientId_;
|
||||||
|
if (ref instanceof java.lang.String) {
|
||||||
|
com.google.protobuf.ByteString b =
|
||||||
|
com.google.protobuf.ByteString.copyFromUtf8(
|
||||||
|
(java.lang.String) ref);
|
||||||
|
recipientId_ = b;
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return (com.google.protobuf.ByteString) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// optional uint32 length = 2;
|
// optional uint32 length = 2;
|
||||||
public static final int LENGTH_FIELD_NUMBER = 2;
|
public static final int LENGTH_FIELD_NUMBER = 2;
|
||||||
private int length_;
|
private int length_;
|
||||||
|
@ -3636,7 +3699,7 @@ public final class BackupProtos {
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
*/
|
*/
|
||||||
public boolean hasLength() {
|
public boolean hasLength() {
|
||||||
return ((bitField0_ & 0x00000002) == 0x00000002);
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
|
@ -3647,6 +3710,7 @@ public final class BackupProtos {
|
||||||
|
|
||||||
private void initFields() {
|
private void initFields() {
|
||||||
name_ = "";
|
name_ = "";
|
||||||
|
recipientId_ = "";
|
||||||
length_ = 0;
|
length_ = 0;
|
||||||
}
|
}
|
||||||
private byte memoizedIsInitialized = -1;
|
private byte memoizedIsInitialized = -1;
|
||||||
|
@ -3664,9 +3728,12 @@ public final class BackupProtos {
|
||||||
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
output.writeBytes(1, getNameBytes());
|
output.writeBytes(1, getNameBytes());
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
output.writeUInt32(2, length_);
|
output.writeUInt32(2, length_);
|
||||||
}
|
}
|
||||||
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
|
output.writeBytes(3, getRecipientIdBytes());
|
||||||
|
}
|
||||||
getUnknownFields().writeTo(output);
|
getUnknownFields().writeTo(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3680,10 +3747,14 @@ public final class BackupProtos {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeBytesSize(1, getNameBytes());
|
.computeBytesSize(1, getNameBytes());
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeUInt32Size(2, length_);
|
.computeUInt32Size(2, length_);
|
||||||
}
|
}
|
||||||
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSize(3, getRecipientIdBytes());
|
||||||
|
}
|
||||||
size += getUnknownFields().getSerializedSize();
|
size += getUnknownFields().getSerializedSize();
|
||||||
memoizedSerializedSize = size;
|
memoizedSerializedSize = size;
|
||||||
return size;
|
return size;
|
||||||
|
@ -3802,8 +3873,10 @@ public final class BackupProtos {
|
||||||
super.clear();
|
super.clear();
|
||||||
name_ = "";
|
name_ = "";
|
||||||
bitField0_ = (bitField0_ & ~0x00000001);
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
length_ = 0;
|
recipientId_ = "";
|
||||||
bitField0_ = (bitField0_ & ~0x00000002);
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
|
length_ = 0;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3839,6 +3912,10 @@ public final class BackupProtos {
|
||||||
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
to_bitField0_ |= 0x00000002;
|
to_bitField0_ |= 0x00000002;
|
||||||
}
|
}
|
||||||
|
result.recipientId_ = recipientId_;
|
||||||
|
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
|
to_bitField0_ |= 0x00000004;
|
||||||
|
}
|
||||||
result.length_ = length_;
|
result.length_ = length_;
|
||||||
result.bitField0_ = to_bitField0_;
|
result.bitField0_ = to_bitField0_;
|
||||||
onBuilt();
|
onBuilt();
|
||||||
|
@ -3861,6 +3938,11 @@ public final class BackupProtos {
|
||||||
name_ = other.name_;
|
name_ = other.name_;
|
||||||
onChanged();
|
onChanged();
|
||||||
}
|
}
|
||||||
|
if (other.hasRecipientId()) {
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
recipientId_ = other.recipientId_;
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
if (other.hasLength()) {
|
if (other.hasLength()) {
|
||||||
setLength(other.getLength());
|
setLength(other.getLength());
|
||||||
}
|
}
|
||||||
|
@ -3965,13 +4047,87 @@ public final class BackupProtos {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// optional string recipientId = 3;
|
||||||
|
private java.lang.Object recipientId_ = "";
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasRecipientId() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getRecipientId() {
|
||||||
|
java.lang.Object ref = recipientId_;
|
||||||
|
if (!(ref instanceof java.lang.String)) {
|
||||||
|
java.lang.String s = ((com.google.protobuf.ByteString) ref)
|
||||||
|
.toStringUtf8();
|
||||||
|
recipientId_ = s;
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return (java.lang.String) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getRecipientIdBytes() {
|
||||||
|
java.lang.Object ref = recipientId_;
|
||||||
|
if (ref instanceof String) {
|
||||||
|
com.google.protobuf.ByteString b =
|
||||||
|
com.google.protobuf.ByteString.copyFromUtf8(
|
||||||
|
(java.lang.String) ref);
|
||||||
|
recipientId_ = b;
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return (com.google.protobuf.ByteString) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public Builder setRecipientId(
|
||||||
|
java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
recipientId_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public Builder clearRecipientId() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
|
recipientId_ = getDefaultInstance().getRecipientId();
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>optional string recipientId = 3;</code>
|
||||||
|
*/
|
||||||
|
public Builder setRecipientIdBytes(
|
||||||
|
com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
recipientId_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// optional uint32 length = 2;
|
// optional uint32 length = 2;
|
||||||
private int length_ ;
|
private int length_ ;
|
||||||
/**
|
/**
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
*/
|
*/
|
||||||
public boolean hasLength() {
|
public boolean hasLength() {
|
||||||
return ((bitField0_ & 0x00000002) == 0x00000002);
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
|
@ -3983,7 +4139,7 @@ public final class BackupProtos {
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
*/
|
*/
|
||||||
public Builder setLength(int value) {
|
public Builder setLength(int value) {
|
||||||
bitField0_ |= 0x00000002;
|
bitField0_ |= 0x00000004;
|
||||||
length_ = value;
|
length_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
|
@ -3992,7 +4148,7 @@ public final class BackupProtos {
|
||||||
* <code>optional uint32 length = 2;</code>
|
* <code>optional uint32 length = 2;</code>
|
||||||
*/
|
*/
|
||||||
public Builder clearLength() {
|
public Builder clearLength() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000002);
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
length_ = 0;
|
length_ = 0;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
|
@ -6692,19 +6848,19 @@ public final class BackupProtos {
|
||||||
"\030\001 \001(\t\022\013\n\003key\030\002 \001(\t\022\r\n\005value\030\003 \001(\t\"A\n\nAt" +
|
"\030\001 \001(\t\022\013\n\003key\030\002 \001(\t\022\r\n\005value\030\003 \001(\t\"A\n\nAt" +
|
||||||
"tachment\022\r\n\005rowId\030\001 \001(\004\022\024\n\014attachmentId\030" +
|
"tachment\022\r\n\005rowId\030\001 \001(\004\022\024\n\014attachmentId\030" +
|
||||||
"\002 \001(\004\022\016\n\006length\030\003 \001(\r\"(\n\007Sticker\022\r\n\005rowI",
|
"\002 \001(\004\022\016\n\006length\030\003 \001(\r\"(\n\007Sticker\022\r\n\005rowI",
|
||||||
"d\030\001 \001(\004\022\016\n\006length\030\002 \001(\r\"&\n\006Avatar\022\014\n\004nam" +
|
"d\030\001 \001(\004\022\016\n\006length\030\002 \001(\r\";\n\006Avatar\022\014\n\004nam" +
|
||||||
"e\030\001 \001(\t\022\016\n\006length\030\002 \001(\r\"\"\n\017DatabaseVersi" +
|
"e\030\001 \001(\t\022\023\n\013recipientId\030\003 \001(\t\022\016\n\006length\030\002" +
|
||||||
"on\022\017\n\007version\030\001 \001(\r\"\"\n\006Header\022\n\n\002iv\030\001 \001(" +
|
" \001(\r\"\"\n\017DatabaseVersion\022\017\n\007version\030\001 \001(\r" +
|
||||||
"\014\022\014\n\004salt\030\002 \001(\014\"\245\002\n\013BackupFrame\022\036\n\006heade" +
|
"\"\"\n\006Header\022\n\n\002iv\030\001 \001(\014\022\014\n\004salt\030\002 \001(\014\"\245\002\n" +
|
||||||
"r\030\001 \001(\0132\016.signal.Header\022\'\n\tstatement\030\002 \001" +
|
"\013BackupFrame\022\036\n\006header\030\001 \001(\0132\016.signal.He" +
|
||||||
"(\0132\024.signal.SqlStatement\022,\n\npreference\030\003" +
|
"ader\022\'\n\tstatement\030\002 \001(\0132\024.signal.SqlStat" +
|
||||||
" \001(\0132\030.signal.SharedPreference\022&\n\nattach" +
|
"ement\022,\n\npreference\030\003 \001(\0132\030.signal.Share" +
|
||||||
"ment\030\004 \001(\0132\022.signal.Attachment\022(\n\007versio" +
|
"dPreference\022&\n\nattachment\030\004 \001(\0132\022.signal" +
|
||||||
"n\030\005 \001(\0132\027.signal.DatabaseVersion\022\013\n\003end\030" +
|
".Attachment\022(\n\007version\030\005 \001(\0132\027.signal.Da" +
|
||||||
"\006 \001(\010\022\036\n\006avatar\030\007 \001(\0132\016.signal.Avatar\022 \n",
|
"tabaseVersion\022\013\n\003end\030\006 \001(\010\022\036\n\006avatar\030\007 \001",
|
||||||
"\007sticker\030\010 \001(\0132\017.signal.StickerB1\n!org.t" +
|
"(\0132\016.signal.Avatar\022 \n\007sticker\030\010 \001(\0132\017.si" +
|
||||||
"houghtcrime.securesms.backupB\014BackupProt" +
|
"gnal.StickerB1\n!org.thoughtcrime.secures" +
|
||||||
"os"
|
"ms.backupB\014BackupProtos"
|
||||||
};
|
};
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||||
|
@ -6746,7 +6902,7 @@ public final class BackupProtos {
|
||||||
internal_static_signal_Avatar_fieldAccessorTable = new
|
internal_static_signal_Avatar_fieldAccessorTable = new
|
||||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||||
internal_static_signal_Avatar_descriptor,
|
internal_static_signal_Avatar_descriptor,
|
||||||
new java.lang.String[] { "Name", "Length", });
|
new java.lang.String[] { "Name", "RecipientId", "Length", });
|
||||||
internal_static_signal_DatabaseVersion_descriptor =
|
internal_static_signal_DatabaseVersion_descriptor =
|
||||||
getDescriptor().getMessageTypes().get(5);
|
getDescriptor().getMessageTypes().get(5);
|
||||||
internal_static_signal_DatabaseVersion_fieldAccessorTable = new
|
internal_static_signal_DatabaseVersion_fieldAccessorTable = new
|
||||||
|
|
|
@ -326,7 +326,7 @@ public class FullBackupExporter extends FullBackupBase {
|
||||||
public void write(@NonNull String avatarName, @NonNull InputStream in, long size) throws IOException {
|
public void write(@NonNull String avatarName, @NonNull InputStream in, long size) throws IOException {
|
||||||
write(outputStream, BackupProtos.BackupFrame.newBuilder()
|
write(outputStream, BackupProtos.BackupFrame.newBuilder()
|
||||||
.setAvatar(BackupProtos.Avatar.newBuilder()
|
.setAvatar(BackupProtos.Avatar.newBuilder()
|
||||||
.setName(avatarName)
|
.setRecipientId(avatarName)
|
||||||
.setLength(Util.toIntExact(size))
|
.setLength(Util.toIntExact(size))
|
||||||
.build())
|
.build())
|
||||||
.build());
|
.build());
|
||||||
|
|
|
@ -27,6 +27,8 @@ import org.thoughtcrime.securesms.database.StickerDatabase;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.Conversions;
|
import org.thoughtcrime.securesms.util.Conversions;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.kdf.HKDFv3;
|
import org.whispersystems.libsignal.kdf.HKDFv3;
|
||||||
|
@ -163,7 +165,10 @@ public class FullBackupImporter extends FullBackupBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processAvatar(@NonNull Context context, @NonNull BackupProtos.Avatar avatar, @NonNull BackupRecordInputStream inputStream) throws IOException {
|
private static void processAvatar(@NonNull Context context, @NonNull BackupProtos.Avatar avatar, @NonNull BackupRecordInputStream inputStream) throws IOException {
|
||||||
inputStream.readAttachmentTo(new FileOutputStream(AvatarHelper.getAvatarFile(context, Address.fromSerialized(PhoneNumberFormatter.get(context).format(avatar.getName())))), avatar.getLength());
|
Recipient recipient = avatar.hasRecipientId() ? Recipient.resolved(RecipientId.from(avatar.getRecipientId()))
|
||||||
|
: Recipient.external(context, avatar.getName());
|
||||||
|
|
||||||
|
inputStream.readAttachmentTo(new FileOutputStream(AvatarHelper.getAvatarFile(context, recipient.getId())), avatar.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ApplySharedPref")
|
@SuppressLint("ApplySharedPref")
|
||||||
|
|
|
@ -6,8 +6,9 @@ import android.net.Uri;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -16,22 +17,22 @@ import java.security.MessageDigest;
|
||||||
|
|
||||||
public class ProfileContactPhoto implements ContactPhoto {
|
public class ProfileContactPhoto implements ContactPhoto {
|
||||||
|
|
||||||
private final @NonNull Address address;
|
private final @NonNull RecipientId recipient;
|
||||||
private final @NonNull String avatarObject;
|
private final @NonNull String avatarObject;
|
||||||
|
|
||||||
public ProfileContactPhoto(@NonNull Address address, @NonNull String avatarObject) {
|
public ProfileContactPhoto(@NonNull RecipientId recipient, @NonNull String avatarObject) {
|
||||||
this.address = address;
|
this.recipient = recipient;
|
||||||
this.avatarObject = avatarObject;
|
this.avatarObject = avatarObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream openInputStream(Context context) throws IOException {
|
public @NonNull InputStream openInputStream(Context context) throws IOException {
|
||||||
return AvatarHelper.getInputStreamFor(context, address);
|
return AvatarHelper.getInputStreamFor(context, recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Uri getUri(@NonNull Context context) {
|
public @Nullable Uri getUri(@NonNull Context context) {
|
||||||
File avatarFile = AvatarHelper.getAvatarFile(context, address);
|
File avatarFile = AvatarHelper.getAvatarFile(context, recipient);
|
||||||
return avatarFile.exists() ? Uri.fromFile(avatarFile) : null;
|
return avatarFile.exists() ? Uri.fromFile(avatarFile) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ public class ProfileContactPhoto implements ContactPhoto {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
||||||
messageDigest.update(address.serialize().getBytes());
|
messageDigest.update(recipient.serialize().getBytes());
|
||||||
messageDigest.update(avatarObject.getBytes());
|
messageDigest.update(avatarObject.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,11 +53,11 @@ public class ProfileContactPhoto implements ContactPhoto {
|
||||||
|
|
||||||
ProfileContactPhoto that = (ProfileContactPhoto)other;
|
ProfileContactPhoto that = (ProfileContactPhoto)other;
|
||||||
|
|
||||||
return this.address.equals(that.address) && this.avatarObject.equals(that.avatarObject);
|
return this.recipient.equals(that.recipient) && this.avatarObject.equals(that.avatarObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return address.hashCode() ^ avatarObject.hashCode();
|
return recipient.hashCode() ^ avatarObject.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintOb
|
||||||
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdFollowUpJobMigration;
|
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdFollowUpJobMigration;
|
||||||
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdFollowUpJobMigration2;
|
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdFollowUpJobMigration2;
|
||||||
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdJobMigration;
|
import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdJobMigration;
|
||||||
|
import org.thoughtcrime.securesms.migrations.AvatarMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.DatabaseMigrationJob;
|
import org.thoughtcrime.securesms.migrations.DatabaseMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
|
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
|
||||||
import org.thoughtcrime.securesms.migrations.MigrationCompleteJob;
|
import org.thoughtcrime.securesms.migrations.MigrationCompleteJob;
|
||||||
|
@ -82,6 +83,7 @@ public final class JobManagerFactories {
|
||||||
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
|
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
|
||||||
|
|
||||||
// Migrations
|
// Migrations
|
||||||
|
put(AvatarMigrationJob.KEY, new AvatarMigrationJob.Factory());
|
||||||
put(DatabaseMigrationJob.KEY, new DatabaseMigrationJob.Factory());
|
put(DatabaseMigrationJob.KEY, new DatabaseMigrationJob.Factory());
|
||||||
put(LegacyMigrationJob.KEY, new LegacyMigrationJob.Factory());
|
put(LegacyMigrationJob.KEY, new LegacyMigrationJob.Factory());
|
||||||
put(MigrationCompleteJob.KEY, new MigrationCompleteJob.Factory());
|
put(MigrationCompleteJob.KEY, new MigrationCompleteJob.Factory());
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class RetrieveProfileAvatarJob extends BaseJob {
|
||||||
|
|
||||||
if (TextUtils.isEmpty(profileAvatar)) {
|
if (TextUtils.isEmpty(profileAvatar)) {
|
||||||
Log.w(TAG, "Removing profile avatar (no url) for: " + recipient.requireAddress().serialize());
|
Log.w(TAG, "Removing profile avatar (no url) for: " + recipient.requireAddress().serialize());
|
||||||
AvatarHelper.delete(context, recipient.requireAddress());
|
AvatarHelper.delete(context, recipient.getId());
|
||||||
database.setProfileAvatar(recipient.getId(), profileAvatar);
|
database.setProfileAvatar(recipient.getId(), profileAvatar);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -104,11 +104,11 @@ public class RetrieveProfileAvatarJob extends BaseJob {
|
||||||
throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e);
|
throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.requireAddress()));
|
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.getId()));
|
||||||
} catch (PushNetworkException e) {
|
} catch (PushNetworkException e) {
|
||||||
if (e.getCause() instanceof NonSuccessfulResponseCodeException) {
|
if (e.getCause() instanceof NonSuccessfulResponseCodeException) {
|
||||||
Log.w(TAG, "Removing profile avatar (no image available) for: " + recipient.requireAddress().serialize());
|
Log.w(TAG, "Removing profile avatar (no image available) for: " + recipient.requireAddress().serialize());
|
||||||
AvatarHelper.delete(context, recipient.requireAddress());
|
AvatarHelper.delete(context, recipient.getId());
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class RotateProfileKeyJob extends BaseJob {
|
||||||
|
|
||||||
private @Nullable StreamDetails getProfileAvatar() {
|
private @Nullable StreamDetails getProfileAvatar() {
|
||||||
try {
|
try {
|
||||||
File avatarFile = AvatarHelper.getAvatarFile(context, Recipient.self().requireAddress());
|
File avatarFile = AvatarHelper.getAvatarFile(context, Recipient.self().getId());
|
||||||
|
|
||||||
if (avatarFile.exists()) {
|
if (avatarFile.exists()) {
|
||||||
return new StreamDetails(new FileInputStream(avatarFile), "image/jpeg", avatarFile.length());
|
return new StreamDetails(new FileInputStream(avatarFile), "image/jpeg", avatarFile.length());
|
||||||
|
|
|
@ -38,13 +38,14 @@ public class ApplicationMigrations {
|
||||||
|
|
||||||
private static final int LEGACY_CANONICAL_VERSION = 455;
|
private static final int LEGACY_CANONICAL_VERSION = 455;
|
||||||
|
|
||||||
public static final int CURRENT_VERSION = 4;
|
public static final int CURRENT_VERSION = 5;
|
||||||
|
|
||||||
private static final class Version {
|
private static final class Version {
|
||||||
static final int LEGACY = 1;
|
static final int LEGACY = 1;
|
||||||
static final int RECIPIENT_ID = 2;
|
static final int RECIPIENT_ID = 2;
|
||||||
static final int RECIPIENT_SEARCH = 3;
|
static final int RECIPIENT_SEARCH = 3;
|
||||||
static final int RECIPIENT_CLEANUP = 4;
|
static final int RECIPIENT_CLEANUP = 4;
|
||||||
|
static final int AVATAR_MIGRATION = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,6 +174,10 @@ public class ApplicationMigrations {
|
||||||
jobs.put(Version.RECIPIENT_CLEANUP, new DatabaseMigrationJob());
|
jobs.put(Version.RECIPIENT_CLEANUP, new DatabaseMigrationJob());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastSeenVersion < Version.AVATAR_MIGRATION) {
|
||||||
|
jobs.put(Version.AVATAR_MIGRATION, new AvatarMigrationJob());
|
||||||
|
}
|
||||||
|
|
||||||
return jobs;
|
return jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package org.thoughtcrime.securesms.migrations;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Previously, we used a recipient's address as the filename for their avatar. We want to use
|
||||||
|
* recipientId's instead in preparation for UUIDs.
|
||||||
|
*/
|
||||||
|
public class AvatarMigrationJob extends MigrationJob {
|
||||||
|
|
||||||
|
public static final String KEY = "AvatarMigrationJob";
|
||||||
|
|
||||||
|
private static final String TAG = Log.tag(AvatarMigrationJob.class);
|
||||||
|
|
||||||
|
AvatarMigrationJob() {
|
||||||
|
this(new Parameters.Builder().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AvatarMigrationJob(@NonNull Parameters parameters) {
|
||||||
|
super(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUiBlocking() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull String getFactoryKey() {
|
||||||
|
return KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performMigration() {
|
||||||
|
File oldDirectory = new File(context.getFilesDir(), "avatars");
|
||||||
|
File[] files = oldDirectory.listFiles();
|
||||||
|
|
||||||
|
Log.i(TAG, "Preparing to move " + files.length + " avatars.");
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
try {
|
||||||
|
Recipient recipient = Recipient.external(context, file.getName());
|
||||||
|
byte[] data = Util.readFully(new FileInputStream(file));
|
||||||
|
|
||||||
|
AvatarHelper.setAvatar(context, recipient.getId(), data);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "Failed to copy avatar file. Skipping it.", e);
|
||||||
|
} finally {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oldDirectory.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean shouldRetry(@NonNull Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory implements Job.Factory<AvatarMigrationJob> {
|
||||||
|
@Override
|
||||||
|
public @NonNull AvatarMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
|
return new AvatarMigrationJob(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ abstract class MigrationJob extends Job {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull Result run() {
|
public @NonNull Result run() {
|
||||||
try {
|
try {
|
||||||
|
Log.i(TAG, "About to run " + getClass().getSimpleName());
|
||||||
performMigration();
|
performMigration();
|
||||||
return Result.success();
|
return Result.success();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -54,7 +55,7 @@ abstract class MigrationJob extends Job {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCanceled() {
|
public void onCanceled() {
|
||||||
throw new AssertionError("This job should never fail.");
|
throw new AssertionError("This job should never fail. " + getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
public class ProfilePreference extends Preference {
|
public class ProfilePreference extends Preference {
|
||||||
|
@ -64,11 +65,11 @@ public class ProfilePreference extends Preference {
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
if (profileNumberView == null) return;
|
if (profileNumberView == null) return;
|
||||||
|
|
||||||
final Address localAddress = Address.fromSerialized(TextSecurePreferences.getLocalNumber(getContext()));
|
final Recipient self = Recipient.self();
|
||||||
final String profileName = TextSecurePreferences.getProfileName(getContext());
|
final String profileName = TextSecurePreferences.getProfileName(getContext());
|
||||||
|
|
||||||
GlideApp.with(getContext().getApplicationContext())
|
GlideApp.with(getContext().getApplicationContext())
|
||||||
.load(new ProfileContactPhoto(localAddress, String.valueOf(TextSecurePreferences.getProfileAvatarId(getContext()))))
|
.load(new ProfileContactPhoto(self.getId(), String.valueOf(TextSecurePreferences.getProfileAvatarId(getContext()))))
|
||||||
.error(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(getContext(), getContext().getResources().getColor(R.color.grey_400)))
|
.error(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(getContext(), getContext().getResources().getColor(R.color.grey_400)))
|
||||||
.circleCrop()
|
.circleCrop()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
|
@ -78,6 +79,6 @@ public class ProfilePreference extends Preference {
|
||||||
profileNameView.setText(profileName);
|
profileNameView.setText(profileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
profileNumberView.setText(localAddress.toPhoneString());
|
profileNumberView.setText(self.requireAddress().toPhoneString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -21,7 +22,7 @@ public class AvatarHelper {
|
||||||
|
|
||||||
private static final String AVATAR_DIRECTORY = "avatars";
|
private static final String AVATAR_DIRECTORY = "avatars";
|
||||||
|
|
||||||
public static InputStream getInputStreamFor(@NonNull Context context, @NonNull Address address)
|
public static InputStream getInputStreamFor(@NonNull Context context, @NonNull RecipientId address)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
return new FileInputStream(getAvatarFile(context, address));
|
return new FileInputStream(getAvatarFile(context, address));
|
||||||
|
@ -35,24 +36,24 @@ public class AvatarHelper {
|
||||||
else return Stream.of(results).toList();
|
else return Stream.of(results).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void delete(@NonNull Context context, @NonNull Address address) {
|
public static void delete(@NonNull Context context, @NonNull RecipientId recipientId) {
|
||||||
getAvatarFile(context, address).delete();
|
getAvatarFile(context, recipientId).delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NonNull File getAvatarFile(@NonNull Context context, @NonNull Address address) {
|
public static @NonNull File getAvatarFile(@NonNull Context context, @NonNull RecipientId recipientId) {
|
||||||
File avatarDirectory = new File(context.getFilesDir(), AVATAR_DIRECTORY);
|
File avatarDirectory = new File(context.getFilesDir(), AVATAR_DIRECTORY);
|
||||||
avatarDirectory.mkdirs();
|
avatarDirectory.mkdirs();
|
||||||
|
|
||||||
return new File(avatarDirectory, new File(address.serialize()).getName());
|
return new File(avatarDirectory, new File(recipientId.serialize()).getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setAvatar(@NonNull Context context, @NonNull Address address, @Nullable byte[] data)
|
public static void setAvatar(@NonNull Context context, @NonNull RecipientId recipientId, @Nullable byte[] data)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
delete(context, address);
|
delete(context, recipientId);
|
||||||
} else {
|
} else {
|
||||||
FileOutputStream out = new FileOutputStream(getAvatarFile(context, address));
|
FileOutputStream out = new FileOutputStream(getAvatarFile(context, recipientId));
|
||||||
out.write(data);
|
out.write(data);
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,7 @@ public class Recipient {
|
||||||
if (localNumber) return null;
|
if (localNumber) return null;
|
||||||
else if (isGroupInternal() && groupAvatarId.isPresent()) return new GroupRecordContactPhoto(address, groupAvatarId.get());
|
else if (isGroupInternal() && groupAvatarId.isPresent()) return new GroupRecordContactPhoto(address, groupAvatarId.get());
|
||||||
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
||||||
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
else if (profileAvatar != null) return new ProfileContactPhoto(id, profileAvatar);
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue