opens existing conversation when participants are the same
This commit is contained in:
parent
5e4476c903
commit
2d070b11a6
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.model;
|
package org.mariotaku.twidere.model;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
@ -34,6 +35,7 @@ import com.hannesdorfmann.parcelableplease.annotation.ParcelableNoThanks;
|
||||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||||
|
|
||||||
import org.mariotaku.commons.objectcursor.LoganSquareCursorFieldConverter;
|
import org.mariotaku.commons.objectcursor.LoganSquareCursorFieldConverter;
|
||||||
|
import org.mariotaku.library.objectcursor.annotation.BeforeWriteContentValues;
|
||||||
import org.mariotaku.library.objectcursor.annotation.CursorField;
|
import org.mariotaku.library.objectcursor.annotation.CursorField;
|
||||||
import org.mariotaku.library.objectcursor.annotation.CursorObject;
|
import org.mariotaku.library.objectcursor.annotation.CursorObject;
|
||||||
import org.mariotaku.twidere.model.message.MessageExtras;
|
import org.mariotaku.twidere.model.message.MessageExtras;
|
||||||
|
@ -42,9 +44,11 @@ import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversat
|
||||||
import org.mariotaku.twidere.model.util.ConversationExtrasConverter;
|
import org.mariotaku.twidere.model.util.ConversationExtrasConverter;
|
||||||
import org.mariotaku.twidere.model.util.MessageExtrasConverter;
|
import org.mariotaku.twidere.model.util.MessageExtrasConverter;
|
||||||
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
|
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
|
||||||
|
import org.mariotaku.twidere.model.util.UserKeysCursorFieldConverter;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations;
|
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -127,6 +131,13 @@ public class ParcelableMessageConversation implements Parcelable {
|
||||||
@CursorField(value = Conversations.PARTICIPANTS, converter = LoganSquareCursorFieldConverter.class)
|
@CursorField(value = Conversations.PARTICIPANTS, converter = LoganSquareCursorFieldConverter.class)
|
||||||
public ParcelableUser[] participants;
|
public ParcelableUser[] participants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys are sorted for string comparison
|
||||||
|
*/
|
||||||
|
@JsonField(name = "participant_keys")
|
||||||
|
@CursorField(value = Conversations.PARTICIPANT_KEYS, converter = UserKeysCursorFieldConverter.class)
|
||||||
|
public UserKey[] participant_keys;
|
||||||
|
|
||||||
@JsonField(name = "sender_key")
|
@JsonField(name = "sender_key")
|
||||||
@CursorField(value = Conversations.SENDER_KEY, converter = UserKeyCursorFieldConverter.class)
|
@CursorField(value = Conversations.SENDER_KEY, converter = UserKeyCursorFieldConverter.class)
|
||||||
public UserKey sender_key;
|
public UserKey sender_key;
|
||||||
|
@ -183,6 +194,7 @@ public class ParcelableMessageConversation implements Parcelable {
|
||||||
void beforeJsonSerialize() {
|
void beforeJsonSerialize() {
|
||||||
internalMessageExtras = ParcelableMessage.InternalExtras.from(message_extras);
|
internalMessageExtras = ParcelableMessage.InternalExtras.from(message_extras);
|
||||||
internalConversationExtras = InternalExtras.from(conversation_extras);
|
internalConversationExtras = InternalExtras.from(conversation_extras);
|
||||||
|
prepareParticipantKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,6 +208,11 @@ public class ParcelableMessageConversation implements Parcelable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeWriteContentValues
|
||||||
|
void beforeWriteContentValues(ContentValues values) throws IOException {
|
||||||
|
prepareParticipantKeys();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ParcelableMessageConversation{" +
|
return "ParcelableMessageConversation{" +
|
||||||
|
@ -227,6 +244,19 @@ public class ParcelableMessageConversation implements Parcelable {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void prepareParticipantKeys() {
|
||||||
|
// Ensure keys are ordered
|
||||||
|
if (participants != null && participant_keys == null) {
|
||||||
|
participant_keys = new UserKey[participants.length];
|
||||||
|
for (int i = 0, j = participants.length; i < j; i++) {
|
||||||
|
participant_keys[i] = participants[i].key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (participant_keys != null) {
|
||||||
|
Arrays.sort(participant_keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@StringDef({ConversationType.ONE_TO_ONE, ConversationType.GROUP})
|
@StringDef({ConversationType.ONE_TO_ONE, ConversationType.GROUP})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface ConversationType {
|
public @interface ConversationType {
|
||||||
|
|
|
@ -380,6 +380,7 @@ public interface TwidereDataStore {
|
||||||
String SPANS = "spans";
|
String SPANS = "spans";
|
||||||
String MESSAGE_EXTRAS = "message_extras";
|
String MESSAGE_EXTRAS = "message_extras";
|
||||||
String PARTICIPANTS = "participants";
|
String PARTICIPANTS = "participants";
|
||||||
|
String PARTICIPANT_KEYS = "participant_keys";
|
||||||
String SENDER_KEY = "sender_key";
|
String SENDER_KEY = "sender_key";
|
||||||
String RECIPIENT_KEY = "recipient_key";
|
String RECIPIENT_KEY = "recipient_key";
|
||||||
String REQUEST_CURSOR = "request_cursor";
|
String REQUEST_CURSOR = "request_cursor";
|
||||||
|
|
|
@ -34,7 +34,7 @@ import static org.mariotaku.twidere.annotation.PreferenceType.STRING;
|
||||||
public interface Constants extends TwidereConstants {
|
public interface Constants extends TwidereConstants {
|
||||||
|
|
||||||
String DATABASES_NAME = "twidere.sqlite";
|
String DATABASES_NAME = "twidere.sqlite";
|
||||||
int DATABASES_VERSION = 179;
|
int DATABASES_VERSION = 180;
|
||||||
|
|
||||||
int EXTRA_FEATURES_NOTICE_VERSION = 0;
|
int EXTRA_FEATURES_NOTICE_VERSION = 0;
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,12 @@
|
||||||
package org.mariotaku.twidere.fragment.message
|
package org.mariotaku.twidere.fragment.message
|
||||||
|
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.support.annotation.WorkerThread
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||||
import android.support.v4.content.Loader
|
import android.support.v4.content.Loader
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
|
@ -37,6 +39,7 @@ import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.ktextension.Bundle
|
import org.mariotaku.ktextension.Bundle
|
||||||
import org.mariotaku.ktextension.set
|
import org.mariotaku.ktextension.set
|
||||||
import org.mariotaku.ktextension.setItemAvailability
|
import org.mariotaku.ktextension.setItemAvailability
|
||||||
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.adapter.SelectableUsersAdapter
|
import org.mariotaku.twidere.adapter.SelectableUsersAdapter
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
|
@ -44,11 +47,8 @@ import org.mariotaku.twidere.constant.nameFirstKey
|
||||||
import org.mariotaku.twidere.extension.model.isOfficial
|
import org.mariotaku.twidere.extension.model.isOfficial
|
||||||
import org.mariotaku.twidere.fragment.BaseFragment
|
import org.mariotaku.twidere.fragment.BaseFragment
|
||||||
import org.mariotaku.twidere.loader.CacheUserSearchLoader
|
import org.mariotaku.twidere.loader.CacheUserSearchLoader
|
||||||
import org.mariotaku.twidere.model.ParcelableMessageConversation
|
import org.mariotaku.twidere.model.*
|
||||||
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
|
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
|
||||||
import org.mariotaku.twidere.model.ParcelableMessageConversationValuesCreator
|
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
|
||||||
import org.mariotaku.twidere.model.UserKey
|
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
|
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
|
||||||
import org.mariotaku.twidere.task.twitter.message.SendMessageTask
|
import org.mariotaku.twidere.task.twitter.message.SendMessageTask
|
||||||
|
@ -235,6 +235,17 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
|
||||||
}
|
}
|
||||||
conversation.participants = (selected + account.user).toTypedArray()
|
conversation.participants = (selected + account.user).toTypedArray()
|
||||||
conversation.is_temp = true
|
conversation.is_temp = true
|
||||||
|
|
||||||
|
if (conversation.conversation_type == ConversationType.ONE_TO_ONE) {
|
||||||
|
val participantKeys = conversation.participants.map(ParcelableUser::key)
|
||||||
|
val existingConversation = findMessageConversation(context, accountKey, participantKeys)
|
||||||
|
if (existingConversation != null) {
|
||||||
|
activity.startActivity(IntentUtils.messageConversation(accountKey, existingConversation.id))
|
||||||
|
activity.finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val values = ParcelableMessageConversationValuesCreator.create(conversation)
|
val values = ParcelableMessageConversationValuesCreator.create(conversation)
|
||||||
context.contentResolver.insert(Conversations.CONTENT_URI, values)
|
context.contentResolver.insert(Conversations.CONTENT_URI, values)
|
||||||
activity.startActivity(IntentUtils.messageConversation(accountKey, conversation.id))
|
activity.startActivity(IntentUtils.messageConversation(accountKey, conversation.id))
|
||||||
|
@ -278,6 +289,25 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun findMessageConversation(context: Context, accountKey: UserKey,
|
||||||
|
participantKeys: Collection<UserKey>): ParcelableMessageConversation? {
|
||||||
|
val resolver = context.contentResolver
|
||||||
|
val where = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY),
|
||||||
|
Expression.equalsArgs(Conversations.PARTICIPANT_KEYS)).sql
|
||||||
|
val whereArgs = arrayOf(accountKey.toString(), participantKeys.sorted().joinToString(","))
|
||||||
|
val cur = resolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, whereArgs, null) ?: return null
|
||||||
|
try {
|
||||||
|
if (cur.moveToFirst()) {
|
||||||
|
return ParcelableMessageConversationCursorIndices.fromCursor(cur)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cur.close()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
internal class PerformSearchRequestRunnable(val query: String, fragment: MessageNewConversationFragment) : Runnable {
|
internal class PerformSearchRequestRunnable(val query: String, fragment: MessageNewConversationFragment) : Runnable {
|
||||||
val fragmentRef = WeakReference(fragment)
|
val fragmentRef = WeakReference(fragment)
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -322,4 +352,5 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -523,6 +523,7 @@ class GetMessagesTask(
|
||||||
this.participants = participants + ParcelableUserUtils.fromUser(user, accountKey)
|
this.participants = participants + ParcelableUserUtils.fromUser(user, accountKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.participant_keys = this.participants.map(ParcelableUser::key).toTypedArray()
|
||||||
this.participants.sortBy(ParcelableUser::screen_name)
|
this.participants.sortBy(ParcelableUser::screen_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue