mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Remove GroupDatabase, RecipientDatabase from DatabaseFactory
This commit is contained in:
@@ -35,8 +35,6 @@ public class DatabaseFactory {
|
||||
|
||||
private final SQLCipherOpenHelper databaseHelper;
|
||||
private final AttachmentDatabase attachments;
|
||||
private final GroupDatabase groupDatabase;
|
||||
private final RecipientDatabase recipientDatabase;
|
||||
|
||||
public static DatabaseFactory getInstance(Context context) {
|
||||
synchronized (lock) {
|
||||
@@ -49,13 +47,6 @@ public class DatabaseFactory {
|
||||
public static AttachmentDatabase getAttachmentDatabase(Context context) {
|
||||
return getInstance(context).attachments;
|
||||
}
|
||||
public static GroupDatabase getGroupDatabase(Context context) {
|
||||
return getInstance(context).groupDatabase;
|
||||
}
|
||||
|
||||
public static RecipientDatabase getRecipientDatabase(Context context) {
|
||||
return getInstance(context).recipientDatabase;
|
||||
}
|
||||
|
||||
private DatabaseFactory(@NonNull Context context) {
|
||||
SQLiteDatabase.loadLibs(context);
|
||||
@@ -65,7 +56,5 @@ public class DatabaseFactory {
|
||||
|
||||
this.databaseHelper = new SQLCipherOpenHelper(context, databaseSecret);
|
||||
this.attachments = new AttachmentDatabase(context, databaseHelper, attachmentSecret);
|
||||
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
||||
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
package org.thoughtcrime.securesms.database;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class GroupDatabase extends Database {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = GroupDatabase.class.getSimpleName();
|
||||
|
||||
static final String TABLE_NAME = "groups";
|
||||
private static final String ID = "_id";
|
||||
static final String GROUP_ID = "group_id";
|
||||
private static final String TITLE = "title";
|
||||
private static final String MEMBERS = "members";
|
||||
private static final String AVATAR = "avatar";
|
||||
private static final String AVATAR_ID = "avatar_id";
|
||||
private static final String AVATAR_KEY = "avatar_key";
|
||||
private static final String AVATAR_CONTENT_TYPE = "avatar_content_type";
|
||||
private static final String AVATAR_RELAY = "avatar_relay";
|
||||
private static final String AVATAR_DIGEST = "avatar_digest";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
private static final String ACTIVE = "active";
|
||||
private static final String MMS = "mms";
|
||||
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
GROUP_ID + " TEXT, " +
|
||||
TITLE + " TEXT, " +
|
||||
MEMBERS + " TEXT, " +
|
||||
AVATAR + " BLOB, " +
|
||||
AVATAR_ID + " INTEGER, " +
|
||||
AVATAR_KEY + " BLOB, " +
|
||||
AVATAR_CONTENT_TYPE + " TEXT, " +
|
||||
AVATAR_RELAY + " TEXT, " +
|
||||
TIMESTAMP + " INTEGER, " +
|
||||
ACTIVE + " INTEGER DEFAULT 1, " +
|
||||
AVATAR_DIGEST + " BLOB, " +
|
||||
MMS + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
|
||||
};
|
||||
|
||||
private static final String[] GROUP_PROJECTION = {
|
||||
GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||
TIMESTAMP, ACTIVE, MMS
|
||||
};
|
||||
|
||||
static final List<String> TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList();
|
||||
|
||||
public GroupDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public Optional<GroupRecord> getGroup(String groupId) {
|
||||
try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, GROUP_ID + " = ?",
|
||||
new String[] {groupId},
|
||||
null, null, null))
|
||||
{
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return getGroup(cursor);
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
Optional<GroupRecord> getGroup(Cursor cursor) {
|
||||
Reader reader = new Reader(cursor);
|
||||
return Optional.fromNullable(reader.getCurrent());
|
||||
}
|
||||
|
||||
public Reader getGroupsFilteredByTitle(String constraint) {
|
||||
@SuppressLint("Recycle")
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, TITLE + " LIKE ?",
|
||||
new String[]{"%" + constraint + "%"},
|
||||
null, null, null);
|
||||
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
public Reader getGroups() {
|
||||
@SuppressLint("Recycle")
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null);
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
public void remove(String groupId, Address source) {
|
||||
List<Address> currentMembers = getCurrentMembers(groupId);
|
||||
currentMembers.remove(source);
|
||||
|
||||
ContentValues contents = new ContentValues();
|
||||
contents.put(MEMBERS, Address.toSerializedList(currentMembers, ','));
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
}
|
||||
|
||||
private List<Address> getCurrentMembers(String groupId) {
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {MEMBERS},
|
||||
GROUP_ID + " = ?",
|
||||
new String[] {groupId},
|
||||
null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS));
|
||||
return Address.fromSerializedList(serializedMembers, ',');
|
||||
}
|
||||
|
||||
return new LinkedList<>();
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Reader implements Closeable {
|
||||
|
||||
private final Cursor cursor;
|
||||
|
||||
public Reader(Cursor cursor) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
public @Nullable GroupRecord getNext() {
|
||||
if (cursor == null || !cursor.moveToNext()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getCurrent();
|
||||
}
|
||||
|
||||
public @Nullable GroupRecord getCurrent() {
|
||||
if (cursor == null || cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new GroupRecord(cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(TITLE)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)),
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(AVATAR_ID)),
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_KEY)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_CONTENT_TYPE)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_RELAY)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1,
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(MMS)) == 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.cursor != null)
|
||||
this.cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GroupRecord {
|
||||
|
||||
private final String id;
|
||||
private final String title;
|
||||
private final List<Address> members;
|
||||
private final byte[] avatar;
|
||||
private final long avatarId;
|
||||
private final boolean active;
|
||||
private final boolean mms;
|
||||
|
||||
public GroupRecord(String id, String title, String members, byte[] avatar,
|
||||
long avatarId, byte[] avatarKey, String avatarContentType,
|
||||
String relay, boolean active, byte[] avatarDigest, boolean mms)
|
||||
{
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.avatar = avatar;
|
||||
this.avatarId = avatarId;
|
||||
this.active = active;
|
||||
this.mms = mms;
|
||||
|
||||
if (!TextUtils.isEmpty(members)) this.members = Address.fromSerializedList(members, ',');
|
||||
else this.members = new LinkedList<>();
|
||||
}
|
||||
|
||||
public byte[] getId() {
|
||||
try {
|
||||
return GroupUtil.getDecodedId(id);
|
||||
} catch (IOException ioe) {
|
||||
throw new AssertionError(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public String getEncodedId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public List<Address> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public byte[] getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public long getAvatarId() {
|
||||
return avatarId;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public boolean isMms() {
|
||||
return mms;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,19 +5,14 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,34 +24,8 @@ public class RecipientDatabase extends Database {
|
||||
private static final String ID = "_id";
|
||||
static final String ADDRESS = "recipient_ids";
|
||||
private static final String BLOCK = "block";
|
||||
private static final String NOTIFICATION = "notification";
|
||||
private static final String VIBRATE = "vibrate";
|
||||
private static final String MUTE_UNTIL = "mute_until";
|
||||
private static final String COLOR = "color";
|
||||
private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
|
||||
private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id";
|
||||
private static final String EXPIRE_MESSAGES = "expire_messages";
|
||||
private static final String REGISTERED = "registered";
|
||||
private static final String PROFILE_KEY = "profile_key";
|
||||
private static final String SYSTEM_DISPLAY_NAME = "system_display_name";
|
||||
private static final String SYSTEM_PHOTO_URI = "system_contact_photo";
|
||||
private static final String SYSTEM_PHONE_LABEL = "system_phone_label";
|
||||
private static final String SYSTEM_CONTACT_URI = "system_contact_uri";
|
||||
private static final String SIGNAL_PROFILE_NAME = "signal_profile_name";
|
||||
private static final String SIGNAL_PROFILE_AVATAR = "signal_profile_avatar";
|
||||
private static final String PROFILE_SHARING = "profile_sharing_approval";
|
||||
private static final String CALL_RINGTONE = "call_ringtone";
|
||||
private static final String CALL_VIBRATE = "call_vibrate";
|
||||
|
||||
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
||||
BLOCK, NOTIFICATION, CALL_RINGTONE, VIBRATE, CALL_VIBRATE, MUTE_UNTIL, COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, EXPIRE_MESSAGES, REGISTERED,
|
||||
PROFILE_KEY, SYSTEM_DISPLAY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_CONTACT_URI,
|
||||
SIGNAL_PROFILE_NAME, SIGNAL_PROFILE_AVATAR, PROFILE_SHARING
|
||||
};
|
||||
|
||||
static final List<String> TYPED_RECIPIENT_PROJECTION = Stream.of(RECIPIENT_PROJECTION)
|
||||
.map(columnName -> TABLE_NAME + "." + columnName)
|
||||
.toList();
|
||||
|
||||
public enum RegisteredState {
|
||||
UNKNOWN(0), REGISTERED(1), NOT_REGISTERED(2);
|
||||
@@ -70,36 +39,8 @@ public class RecipientDatabase extends Database {
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static RegisteredState fromId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
}
|
||||
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
ADDRESS + " TEXT UNIQUE, " +
|
||||
BLOCK + " INTEGER DEFAULT 0," +
|
||||
NOTIFICATION + " TEXT DEFAULT NULL, " +
|
||||
VIBRATE + " INTEGER DEFAULT 0, " +
|
||||
MUTE_UNTIL + " INTEGER DEFAULT 0, " +
|
||||
COLOR + " TEXT DEFAULT NULL, " +
|
||||
SEEN_INVITE_REMINDER + " INTEGER DEFAULT 0, " +
|
||||
DEFAULT_SUBSCRIPTION_ID + " INTEGER DEFAULT -1, " +
|
||||
EXPIRE_MESSAGES + " INTEGER DEFAULT 0, " +
|
||||
REGISTERED + " INTEGER DEFAULT 0, " +
|
||||
SYSTEM_DISPLAY_NAME + " TEXT DEFAULT NULL, " +
|
||||
SYSTEM_PHOTO_URI + " TEXT DEFAULT NULL, " +
|
||||
SYSTEM_PHONE_LABEL + " TEXT DEFAULT NULL, " +
|
||||
SYSTEM_CONTACT_URI + " TEXT DEFAULT NULL, " +
|
||||
PROFILE_KEY + " TEXT DEFAULT NULL, " +
|
||||
SIGNAL_PROFILE_NAME + " TEXT DEFAULT NULL, " +
|
||||
SIGNAL_PROFILE_AVATAR + " TEXT DEFAULT NULL, " +
|
||||
PROFILE_SHARING + " INTEGER DEFAULT 0, " +
|
||||
CALL_RINGTONE + " TEXT DEFAULT NULL, " +
|
||||
CALL_VIBRATE + " INTEGER DEFAULT 0);";
|
||||
|
||||
public RecipientDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
@@ -111,67 +52,6 @@ public class RecipientDatabase extends Database {
|
||||
null, null, null, null, null);
|
||||
}
|
||||
|
||||
public Optional<RecipientSettings> getRecipientSettings(@NonNull Address address) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[] {address.serialize()}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return getRecipientSettings(cursor);
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
Optional<RecipientSettings> getRecipientSettings(@NonNull Cursor cursor) {
|
||||
boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
|
||||
long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL));
|
||||
String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR));
|
||||
boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
|
||||
int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID));
|
||||
int expireMessages = cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRE_MESSAGES));
|
||||
int registeredState = cursor.getInt(cursor.getColumnIndexOrThrow(REGISTERED));
|
||||
String profileKeyString = cursor.getString(cursor.getColumnIndexOrThrow(PROFILE_KEY));
|
||||
String systemDisplayName = cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_DISPLAY_NAME));
|
||||
String systemContactPhoto = cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_PHOTO_URI));
|
||||
String systemPhoneLabel = cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_PHONE_LABEL));
|
||||
String systemContactUri = cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_CONTACT_URI));
|
||||
String signalProfileName = cursor.getString(cursor.getColumnIndexOrThrow(SIGNAL_PROFILE_NAME));
|
||||
String signalProfileAvatar = cursor.getString(cursor.getColumnIndexOrThrow(SIGNAL_PROFILE_AVATAR));
|
||||
|
||||
MaterialColor color;
|
||||
byte[] profileKey = null;
|
||||
|
||||
try {
|
||||
color = serializedColor == null ? null : MaterialColor.fromSerialized(serializedColor);
|
||||
} catch (MaterialColor.UnknownColorException e) {
|
||||
Log.w(TAG, e);
|
||||
color = null;
|
||||
}
|
||||
|
||||
if (profileKeyString != null) {
|
||||
try {
|
||||
profileKey = Base64.decode(profileKeyString);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
profileKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(new RecipientSettings(blocked, muteUntil,
|
||||
color, seenInviteReminder,
|
||||
defaultSubscriptionId, expireMessages,
|
||||
RegisteredState.fromId(registeredState),
|
||||
profileKey, systemDisplayName, systemContactPhoto,
|
||||
systemPhoneLabel, systemContactUri,
|
||||
signalProfileName, signalProfileAvatar));
|
||||
}
|
||||
|
||||
public void setColor(@NonNull Recipient recipient, @NonNull MaterialColor color) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(COLOR, color.serialize());
|
||||
|
||||
@@ -41,12 +41,8 @@ import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.SystemContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.TransparentContactPhoto;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
|
||||
@@ -57,7 +53,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Recipient implements RecipientModifiedListener {
|
||||
|
||||
@@ -116,100 +111,7 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return dcContext.getRecipient(dcContext.getContact(contactId));
|
||||
}
|
||||
}
|
||||
return provider.getRecipient(context, address, Optional.absent(), Optional.absent(), asynchronous);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, @NonNull Optional<RecipientSettings> settings, @NonNull Optional<GroupDatabase.GroupRecord> groupRecord, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, settings, groupRecord, asynchronous);
|
||||
}
|
||||
|
||||
Recipient(@NonNull Address address,
|
||||
@Nullable Recipient stale,
|
||||
@NonNull Optional<RecipientDetails> details,
|
||||
@NonNull ListenableFutureTask<RecipientDetails> future)
|
||||
{
|
||||
this.address = address;
|
||||
this.color = null;
|
||||
this.resolving = true;
|
||||
|
||||
if (stale != null) {
|
||||
this.name = stale.name;
|
||||
this.contactUri = stale.contactUri;
|
||||
this.systemContactPhoto = stale.systemContactPhoto;
|
||||
this.color = stale.color;
|
||||
this.customLabel = stale.customLabel;
|
||||
this.messageRingtone = stale.messageRingtone;
|
||||
this.callRingtone = stale.callRingtone;
|
||||
this.blocked = stale.blocked;
|
||||
this.expireMessages = stale.expireMessages;
|
||||
this.seenInviteReminder = stale.seenInviteReminder;
|
||||
this.defaultSubscriptionId = stale.defaultSubscriptionId;
|
||||
this.registered = stale.registered;
|
||||
this.profileKey = stale.profileKey;
|
||||
this.profileName = stale.profileName;
|
||||
this.profileAvatar = stale.profileAvatar;
|
||||
this.participants.clear();
|
||||
this.participants.addAll(stale.participants);
|
||||
}
|
||||
|
||||
if (details.isPresent()) {
|
||||
this.name = details.get().name;
|
||||
this.systemContactPhoto = details.get().systemContactPhoto;
|
||||
this.color = details.get().color;
|
||||
this.blocked = details.get().blocked;
|
||||
this.expireMessages = details.get().expireMessages;
|
||||
this.seenInviteReminder = details.get().seenInviteReminder;
|
||||
this.defaultSubscriptionId = details.get().defaultSubscriptionId;
|
||||
this.registered = details.get().registered;
|
||||
this.profileKey = details.get().profileKey;
|
||||
this.profileName = details.get().profileName;
|
||||
this.profileAvatar = details.get().profileAvatar;
|
||||
this.participants.clear();
|
||||
this.participants.addAll(details.get().participants);
|
||||
}
|
||||
|
||||
future.addListener(new FutureTaskListener<RecipientDetails>() {
|
||||
@Override
|
||||
public void onSuccess(RecipientDetails result) {
|
||||
if (result != null) {
|
||||
synchronized (Recipient.this) {
|
||||
Recipient.this.name = result.name;
|
||||
Recipient.this.contactUri = result.contactUri;
|
||||
Recipient.this.systemContactPhoto = result.systemContactPhoto;
|
||||
Recipient.this.color = result.color;
|
||||
Recipient.this.customLabel = result.customLabel;
|
||||
Recipient.this.blocked = result.blocked;
|
||||
Recipient.this.expireMessages = result.expireMessages;
|
||||
Recipient.this.seenInviteReminder = result.seenInviteReminder;
|
||||
Recipient.this.defaultSubscriptionId = result.defaultSubscriptionId;
|
||||
Recipient.this.registered = result.registered;
|
||||
Recipient.this.profileKey = result.profileKey;
|
||||
Recipient.this.profileName = result.profileName;
|
||||
Recipient.this.profileAvatar = result.profileAvatar;
|
||||
Recipient.this.profileName = result.profileName;
|
||||
|
||||
Recipient.this.participants.clear();
|
||||
Recipient.this.participants.addAll(result.participants);
|
||||
Recipient.this.resolving = false;
|
||||
|
||||
if (!listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.addListener(Recipient.this);
|
||||
}
|
||||
|
||||
Recipient.this.notifyAll();
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException error) {
|
||||
Log.w(TAG, error);
|
||||
}
|
||||
});
|
||||
return dcContext.getRecipient(dcContext.getContact(0));
|
||||
}
|
||||
|
||||
public Recipient(@NonNull Address address, @NonNull RecipientDetails details) {
|
||||
@@ -417,10 +319,6 @@ public class Recipient implements RecipientModifiedListener {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized int getExpireMessages() {
|
||||
return expireMessages;
|
||||
}
|
||||
|
||||
public synchronized RegisteredState getRegistered() {
|
||||
if (isPushGroupRecipient()) return RegisteredState.REGISTERED;
|
||||
else if (isMmsGroupRecipient()) return RegisteredState.NOT_REGISTERED;
|
||||
@@ -441,10 +339,6 @@ public class Recipient implements RecipientModifiedListener {
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isSystemContact() {
|
||||
return contactUri != null;
|
||||
}
|
||||
|
||||
public synchronized Recipient resolve() {
|
||||
while (resolving) Util.wait(this, 0);
|
||||
return this;
|
||||
|
||||
@@ -16,21 +16,13 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.SoftHashMap;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
|
||||
@@ -38,118 +30,16 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class RecipientProvider {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = RecipientProvider.class.getSimpleName();
|
||||
|
||||
private static final RecipientCache recipientCache = new RecipientCache();
|
||||
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
|
||||
|
||||
private static final Map<String, RecipientDetails> STATIC_DETAILS = new HashMap<String, RecipientDetails>() {{
|
||||
put("262966", new RecipientDetails("Amazon", null, false, null, null));
|
||||
}};
|
||||
|
||||
@NonNull Recipient getRecipient(@NonNull Context context, @NonNull Address address, @NonNull Optional<RecipientSettings> settings, @NonNull Optional<GroupRecord> groupRecord, boolean asynchronous) {
|
||||
Recipient cachedRecipient = recipientCache.get(address);
|
||||
|
||||
if (cachedRecipient != null && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
Optional<RecipientDetails> prefetchedRecipientDetails = createPrefetchedRecipientDetails(context, address, settings, groupRecord);
|
||||
|
||||
if (asynchronous) {
|
||||
cachedRecipient = new Recipient(address, cachedRecipient, prefetchedRecipientDetails, getRecipientDetailsAsync(context, address, settings, groupRecord));
|
||||
} else {
|
||||
cachedRecipient = new Recipient(address, getRecipientDetailsSync(context, address, settings, groupRecord, false));
|
||||
}
|
||||
|
||||
recipientCache.set(address, cachedRecipient);
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
@NonNull Optional<Recipient> getCached(@NonNull Address address) {
|
||||
return Optional.fromNullable(recipientCache.get(address));
|
||||
}
|
||||
|
||||
private @NonNull Optional<RecipientDetails> createPrefetchedRecipientDetails(@NonNull Context context, @NonNull Address address,
|
||||
@NonNull Optional<RecipientSettings> settings,
|
||||
@NonNull Optional<GroupRecord> groupRecord)
|
||||
{
|
||||
if (address.isGroup() && settings.isPresent() && groupRecord.isPresent()) {
|
||||
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
||||
} else if (!address.isGroup() && settings.isPresent()) {
|
||||
return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), settings.get(), null));
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
private @NonNull ListenableFutureTask<RecipientDetails> getRecipientDetailsAsync(final Context context, final @NonNull Address address, final @NonNull Optional<RecipientSettings> settings, final @NonNull Optional<GroupRecord> groupRecord)
|
||||
{
|
||||
Callable<RecipientDetails> task = () -> getRecipientDetailsSync(context, address, settings, groupRecord, true);
|
||||
|
||||
ListenableFutureTask<RecipientDetails> future = new ListenableFutureTask<>(task);
|
||||
asyncRecipientResolver.submit(future);
|
||||
return future;
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean nestedAsynchronous) {
|
||||
if (address.isGroup()) return getGroupRecipientDetails(context, address, groupRecord, settings, nestedAsynchronous);
|
||||
else return getIndividualRecipientDetails(context, address, settings);
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getIndividualRecipientDetails(Context context, @NonNull Address address, Optional<RecipientSettings> settings) {
|
||||
if (!settings.isPresent()) {
|
||||
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address);
|
||||
}
|
||||
|
||||
if (!settings.isPresent() && STATIC_DETAILS.containsKey(address.serialize())) {
|
||||
return STATIC_DETAILS.get(address.serialize());
|
||||
} else {
|
||||
boolean systemContact = settings.isPresent() && !TextUtils.isEmpty(settings.get().getSystemDisplayName());
|
||||
return new RecipientDetails(null, null, systemContact, settings.orNull(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getGroupRecipientDetails(Context context, Address groupId, Optional<GroupRecord> groupRecord, Optional<RecipientSettings> settings, boolean asynchronous) {
|
||||
|
||||
if (!groupRecord.isPresent()) {
|
||||
groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(groupId.toGroupString());
|
||||
}
|
||||
|
||||
if (!settings.isPresent()) {
|
||||
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(groupId);
|
||||
}
|
||||
|
||||
if (groupRecord.isPresent()) {
|
||||
String title = groupRecord.get().getTitle();
|
||||
List<Address> memberAddresses = groupRecord.get().getMembers();
|
||||
List<Recipient> members = new LinkedList<>();
|
||||
Long avatarId = null;
|
||||
|
||||
for (Address memberAddress : memberAddresses) {
|
||||
members.add(getRecipient(context, memberAddress, Optional.absent(), Optional.absent(), asynchronous));
|
||||
}
|
||||
|
||||
if (!groupId.isMmsGroup() && title == null) {
|
||||
title = context.getString(R.string.RecipientProvider_unnamed_group);
|
||||
}
|
||||
|
||||
if (groupRecord.get().getAvatar() != null && groupRecord.get().getAvatar().length > 0) {
|
||||
avatarId = groupRecord.get().getAvatarId();
|
||||
}
|
||||
|
||||
return new RecipientDetails(title, avatarId, false, settings.orNull(), members);
|
||||
}
|
||||
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, false, settings.orNull(), null);
|
||||
}
|
||||
|
||||
public static class RecipientDetails {
|
||||
@Nullable final String name;
|
||||
@Nullable final String customLabel;
|
||||
@@ -192,19 +82,4 @@ public class RecipientProvider {
|
||||
else this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RecipientCache {
|
||||
|
||||
private final Map<Address,Recipient> cache = new SoftHashMap<>(1000);
|
||||
|
||||
public synchronized Recipient get(Address address) {
|
||||
return cache.get(address);
|
||||
}
|
||||
|
||||
public synchronized void set(Address address, Recipient recipient) {
|
||||
cache.put(address, recipient);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user