mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-25 15:37:32 +00:00
Add support for syncing pinned status with storage service.
This commit is contained in:
@@ -3,10 +3,14 @@ package org.whispersystems.signalservice.api.storage;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
||||
import org.whispersystems.signalservice.api.util.ProtoUtil;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class SignalAccountRecord implements SignalRecord {
|
||||
@@ -15,20 +19,26 @@ public final class SignalAccountRecord implements SignalRecord {
|
||||
private final AccountRecord proto;
|
||||
private final boolean hasUnknownFields;
|
||||
|
||||
private final Optional<String> givenName;
|
||||
private final Optional<String> familyName;
|
||||
private final Optional<String> avatarUrlPath;
|
||||
private final Optional<byte[]> profileKey;
|
||||
private final Optional<String> givenName;
|
||||
private final Optional<String> familyName;
|
||||
private final Optional<String> avatarUrlPath;
|
||||
private final Optional<byte[]> profileKey;
|
||||
private final List<PinnedConversation> pinnedConversations;
|
||||
|
||||
public SignalAccountRecord(StorageId id, AccountRecord proto) {
|
||||
this.id = id;
|
||||
this.proto = proto;
|
||||
this.hasUnknownFields = ProtoUtil.hasUnknownFields(proto);
|
||||
|
||||
this.givenName = OptionalUtil.absentIfEmpty(proto.getGivenName());
|
||||
this.familyName = OptionalUtil.absentIfEmpty(proto.getFamilyName());
|
||||
this.profileKey = OptionalUtil.absentIfEmpty(proto.getProfileKey());
|
||||
this.avatarUrlPath = OptionalUtil.absentIfEmpty(proto.getAvatarUrlPath());
|
||||
this.givenName = OptionalUtil.absentIfEmpty(proto.getGivenName());
|
||||
this.familyName = OptionalUtil.absentIfEmpty(proto.getFamilyName());
|
||||
this.profileKey = OptionalUtil.absentIfEmpty(proto.getProfileKey());
|
||||
this.avatarUrlPath = OptionalUtil.absentIfEmpty(proto.getAvatarUrlPath());
|
||||
this.pinnedConversations = new ArrayList<>(proto.getPinnedConversationsCount());
|
||||
|
||||
for (AccountRecord.PinnedConversation conversation : proto.getPinnedConversationsList()) {
|
||||
pinnedConversations.add(PinnedConversation.fromRemote(conversation));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,6 +102,10 @@ public final class SignalAccountRecord implements SignalRecord {
|
||||
return proto.getUnlistedPhoneNumber();
|
||||
}
|
||||
|
||||
public List<PinnedConversation> getPinnedConversations() {
|
||||
return pinnedConversations;
|
||||
}
|
||||
|
||||
AccountRecord toProto() {
|
||||
return proto;
|
||||
}
|
||||
@@ -110,6 +124,96 @@ public final class SignalAccountRecord implements SignalRecord {
|
||||
return Objects.hash(id, proto);
|
||||
}
|
||||
|
||||
public static class PinnedConversation {
|
||||
private final Optional<SignalServiceAddress> contact;
|
||||
private final Optional<byte[]> groupV1Id;
|
||||
private final Optional<byte[]> groupV2MasterKey;
|
||||
|
||||
private PinnedConversation(Optional<SignalServiceAddress> contact, Optional<byte[]> groupV1Id, Optional<byte[]> groupV2MasterKey) {
|
||||
this.contact = contact;
|
||||
this.groupV1Id = groupV1Id;
|
||||
this.groupV2MasterKey = groupV2MasterKey;
|
||||
}
|
||||
|
||||
public static PinnedConversation forContact(SignalServiceAddress address) {
|
||||
return new PinnedConversation(Optional.of(address), Optional.absent(), Optional.absent());
|
||||
}
|
||||
|
||||
public static PinnedConversation forGroupV1(byte[] groupId) {
|
||||
return new PinnedConversation(Optional.absent(), Optional.of(groupId), Optional.absent());
|
||||
}
|
||||
|
||||
public static PinnedConversation forGroupV2(byte[] masterKey) {
|
||||
return new PinnedConversation(Optional.absent(), Optional.absent(), Optional.of(masterKey));
|
||||
}
|
||||
|
||||
private static PinnedConversation forEmpty() {
|
||||
return new PinnedConversation(Optional.absent(), Optional.absent(), Optional.absent());
|
||||
}
|
||||
|
||||
static PinnedConversation fromRemote(AccountRecord.PinnedConversation remote) {
|
||||
if (remote.hasContact()) {
|
||||
return forContact(new SignalServiceAddress(UuidUtil.parseOrNull(remote.getContact().getUuid()), remote.getContact().getE164()));
|
||||
} else if (!remote.getLegacyGroupId().isEmpty()) {
|
||||
return forGroupV1(remote.getLegacyGroupId().toByteArray());
|
||||
} else if (!remote.getGroupMasterKey().isEmpty()) {
|
||||
return forGroupV2(remote.getGroupMasterKey().toByteArray());
|
||||
} else {
|
||||
return PinnedConversation.forEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<SignalServiceAddress> getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public Optional<byte[]> getGroupV1Id() {
|
||||
return groupV1Id;
|
||||
}
|
||||
|
||||
public Optional<byte[]> getGroupV2MasterKey() {
|
||||
return groupV2MasterKey;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return contact.isPresent() || groupV1Id.isPresent() || groupV2MasterKey.isPresent();
|
||||
}
|
||||
|
||||
private AccountRecord.PinnedConversation toRemote() {
|
||||
if (contact.isPresent()) {
|
||||
AccountRecord.PinnedConversation.Contact.Builder contactBuilder = AccountRecord.PinnedConversation.Contact.newBuilder();
|
||||
if (contact.get().getUuid().isPresent()) {
|
||||
contactBuilder.setUuid(contact.get().getUuid().get().toString());
|
||||
}
|
||||
if (contact.get().getNumber().isPresent()) {
|
||||
contactBuilder.setE164(contact.get().getNumber().get());
|
||||
}
|
||||
return AccountRecord.PinnedConversation.newBuilder().setContact(contactBuilder.build()).build();
|
||||
} else if (groupV1Id.isPresent()) {
|
||||
return AccountRecord.PinnedConversation.newBuilder().setLegacyGroupId(ByteString.copyFrom(groupV1Id.get())).build();
|
||||
} else if (groupV2MasterKey.isPresent()) {
|
||||
return AccountRecord.PinnedConversation.newBuilder().setGroupMasterKey(ByteString.copyFrom(groupV2MasterKey.get())).build();
|
||||
} else {
|
||||
return AccountRecord.PinnedConversation.newBuilder().build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PinnedConversation that = (PinnedConversation) o;
|
||||
return contact.equals(that.contact) &&
|
||||
groupV1Id.equals(that.groupV1Id) &&
|
||||
groupV2MasterKey.equals(that.groupV2MasterKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(contact, groupV1Id, groupV2MasterKey);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private final StorageId id;
|
||||
private final AccountRecord.Builder builder;
|
||||
@@ -186,6 +290,16 @@ public final class SignalAccountRecord implements SignalRecord {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPinnedConversations(List<PinnedConversation> pinnedConversations) {
|
||||
builder.clearPinnedConversations();
|
||||
|
||||
for (PinnedConversation pinned : pinnedConversations) {
|
||||
builder.addPinnedConversations(pinned.toRemote());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignalAccountRecord build() {
|
||||
AccountRecord proto = builder.build();
|
||||
|
||||
|
@@ -107,17 +107,31 @@ message AccountRecord {
|
||||
NOBODY = 2;
|
||||
}
|
||||
|
||||
bytes profileKey = 1;
|
||||
string givenName = 2;
|
||||
string familyName = 3;
|
||||
string avatarUrlPath = 4;
|
||||
bool noteToSelfArchived = 5;
|
||||
bool readReceipts = 6;
|
||||
bool sealedSenderIndicators = 7;
|
||||
bool typingIndicators = 8;
|
||||
bool proxiedLinkPreviews = 9;
|
||||
bool noteToSelfMarkedUnread = 10;
|
||||
bool linkPreviews = 11;
|
||||
PhoneNumberSharingMode phoneNumberSharingMode = 12;
|
||||
bool unlistedPhoneNumber = 13;
|
||||
message PinnedConversation {
|
||||
message Contact {
|
||||
string uuid = 1;
|
||||
string e164 = 2;
|
||||
}
|
||||
|
||||
oneof identifier {
|
||||
Contact contact = 1;
|
||||
bytes legacyGroupId = 3;
|
||||
bytes groupMasterKey = 4;
|
||||
}
|
||||
}
|
||||
|
||||
bytes profileKey = 1;
|
||||
string givenName = 2;
|
||||
string familyName = 3;
|
||||
string avatarUrlPath = 4;
|
||||
bool noteToSelfArchived = 5;
|
||||
bool readReceipts = 6;
|
||||
bool sealedSenderIndicators = 7;
|
||||
bool typingIndicators = 8;
|
||||
bool proxiedLinkPreviews = 9;
|
||||
bool noteToSelfMarkedUnread = 10;
|
||||
bool linkPreviews = 11;
|
||||
PhoneNumberSharingMode phoneNumberSharingMode = 12;
|
||||
bool unlistedPhoneNumber = 13;
|
||||
repeated PinnedConversation pinnedConversations = 14;
|
||||
}
|
||||
|
Reference in New Issue
Block a user