Skip to content

Commit

Permalink
Migrate conversation rendering to the paging library.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal authored and alex-signal committed May 14, 2020
1 parent 9ac1897 commit b750888
Show file tree
Hide file tree
Showing 13 changed files with 657 additions and 710 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ dependencies {
implementation "androidx.camera:camera-lifecycle:1.0.0-beta01"
implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.autofill:autofill:1.0.0"
implementation "androidx.paging:paging-common:2.1.2"
implementation "androidx.paging:paging-runtime:2.1.2"


implementation('com.google.firebase:firebase-messaging:17.3.4') {
exclude group: 'com.google.firebase', module: 'firebase-core'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,6 @@ public void onActivityResult(final int reqCode, int resultCode, Intent data) {
break;
case ADD_CONTACT:
onRecipientChanged(recipient.get());
fragment.reloadList();
break;
case PICK_LOCATION:
SignalPlace place = new SignalPlace(PlacePickerActivity.addressFromData(data));
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,82 +1,49 @@
package org.thoughtcrime.securesms.conversation;

import android.database.Cursor;

import androidx.annotation.NonNull;

public final class ConversationData {
private final Cursor cursor;
private final int offset;
private final int limit;
/**
* Represents metadata about a conversation.
*/
final class ConversationData {
private final long lastSeen;
private final int previousOffset;
private final boolean firstLoad;
private final boolean hasSent;
private final boolean isMessageRequestAccepted;
private final boolean hasPreMessageRequestMessages;
private final int jumpToPosition;

public ConversationData(Cursor cursor,
int offset,
int limit,
long lastSeen,
int previousOffset,
boolean firstLoad,
boolean hasSent,
boolean isMessageRequestAccepted,
boolean hasPreMessageRequestMessages)
ConversationData(long lastSeen,
boolean hasSent,
boolean isMessageRequestAccepted,
boolean hasPreMessageRequestMessages,
int jumpToPosition)
{
this.cursor = cursor;
this.offset = offset;
this.limit = limit;
this.lastSeen = lastSeen;
this.previousOffset = previousOffset;
this.firstLoad = firstLoad;
this.hasSent = hasSent;
this.isMessageRequestAccepted = isMessageRequestAccepted;
this.hasPreMessageRequestMessages = hasPreMessageRequestMessages;
this.jumpToPosition = jumpToPosition;
}

public @NonNull Cursor getCursor() {
return cursor;
}

public boolean hasLimit() {
return limit > 0;
}

public int getLimit() {
return limit;
}

public boolean hasOffset() {
return offset > 0;
}

public int getOffset() {
return offset;
}

public int getPreviousOffset() {
return previousOffset;
}

public long getLastSeen() {
long getLastSeen() {
return lastSeen;
}

public boolean isFirstLoad() {
return firstLoad;
}

public boolean hasSent() {
boolean hasSent() {
return hasSent;
}

public boolean isMessageRequestAccepted() {
boolean isMessageRequestAccepted() {
return isMessageRequestAccepted;
}

public boolean hasPreMessageRequestMessages() {
boolean hasPreMessageRequestMessages() {
return hasPreMessageRequestMessages;
}

boolean shouldJumpToMessage() {
return jumpToPosition >= 0;
}

int getJumpToPosition() {
return jumpToPosition;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.thoughtcrime.securesms.conversation;

import android.content.Context;
import android.database.ContentObserver;

import androidx.annotation.NonNull;
import androidx.paging.DataSource;
import androidx.paging.PositionalDataSource;

import org.thoughtcrime.securesms.database.DatabaseContentProviders;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.logging.Log;

import java.util.ArrayList;
import java.util.List;

/**
* Core data source for loading an individual conversation.
*/
class ConversationDataSource extends PositionalDataSource<MessageRecord> {

private static final String TAG = Log.tag(ConversationDataSource.class);

private final Context context;
private final long threadId;

private ConversationDataSource(@NonNull Context context, long threadId) {
this.context = context;
this.threadId = threadId;

ContentObserver contentObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
invalidate();
context.getContentResolver().unregisterContentObserver(this);
}
};

context.getContentResolver().registerContentObserver(DatabaseContentProviders.Conversation.getUriForThread(threadId), true, contentObserver);
}

@Override
public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<MessageRecord> callback) {
long start = System.currentTimeMillis();

MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context);
List<MessageRecord> records = new ArrayList<>(params.requestedLoadSize);

try (MmsSmsDatabase.Reader reader = db.readerFor(db.getConversation(threadId, params.requestedStartPosition, params.requestedLoadSize))) {
MessageRecord record;
while ((record = reader.getNext()) != null && !isInvalid()) {
records.add(record);
}
}

callback.onResult(records, params.requestedStartPosition, db.getConversationCount(threadId));
Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : ""));
}

@Override
public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<MessageRecord> callback) {
long start = System.currentTimeMillis();

MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context);
List<MessageRecord> records = new ArrayList<>(params.loadSize);

try (MmsSmsDatabase.Reader reader = db.readerFor(db.getConversation(threadId, params.startPosition, params.loadSize))) {
MessageRecord record;
while ((record = reader.getNext()) != null && !isInvalid()) {
records.add(record);
}
}

callback.onResult(records);
Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : ""));
}

static class Factory extends DataSource.Factory<Integer, MessageRecord> {

private final Context context;
private final long threadId;

Factory(Context context, long threadId) {
this.context = context;
this.threadId = threadId;
}

@Override
public @NonNull DataSource<Integer, MessageRecord> create() {
return new ConversationDataSource(context, threadId);
}
}
}

0 comments on commit b750888

Please sign in to comment.