implementing messages refresh

This commit is contained in:
Mariotaku Lee 2017-02-11 01:03:40 +08:00
parent 90cb5770e9
commit 23dd621445
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
5 changed files with 100 additions and 76 deletions

View File

@ -432,8 +432,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
}.alwaysUi {
val activity = weakThis.get() ?: return@alwaysUi
if (activity.isFinishing) return@alwaysUi
val df = weakDf.get() ?: supportFragmentManager.findFragmentByTag(FRAGMENT_TAG_LOADING_DEFAULT_FEATURES) as? DialogFragment
df?.dismiss()
activity.executeAfterFragmentResumed { activity ->
val fm = activity.supportFragmentManager
val df = weakDf.get() ?: fm.findFragmentByTag(FRAGMENT_TAG_LOADING_DEFAULT_FEATURES) as? DialogFragment
df?.dismiss()
}
}
}

View File

@ -1,27 +1,24 @@
package org.mariotaku.twidere.fragment
import android.accounts.AccountManager
import android.content.Context
import android.os.Bundle
import android.support.v4.app.LoaderManager
import android.support.v4.content.Loader
import com.squareup.otto.Subscribe
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.toNulls
import org.mariotaku.sqliteqb.library.OrderBy
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.MessagesEntriesAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.extension.model.user
import org.mariotaku.twidere.loader.ObjectCursorLoader
import org.mariotaku.twidere.model.ParcelableMessageConversation
import org.mariotaku.twidere.model.ParcelableMessageConversationCursorIndices
import org.mariotaku.twidere.model.SimpleRefreshTaskParam
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.task.GetMessagesTask
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.ErrorInfoStore
import org.mariotaku.twidere.util.IntentUtils
@ -45,6 +42,16 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
loaderManager.initLoader(0, null, this)
}
override fun onStart() {
super.onStart()
bus.register(this)
}
override fun onStop() {
bus.unregister(this)
super.onStop()
}
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<ParcelableMessageConversation>?> {
val loader = ObjectCursorLoader(context, ParcelableMessageConversationCursorIndices::class.java)
loader.uri = Conversations.CONTENT_URI
@ -69,37 +76,8 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
override fun triggerRefresh(): Boolean {
super.triggerRefresh()
twitterWrapper.getMessagesAsync(object : SimpleRefreshTaskParam() {
private val accounts by lazy {
AccountUtils.getAllAccountDetails(AccountManager.get(context), accountKeys, false)
}
override val accountKeys: Array<UserKey> by lazy {
this@MessagesEntriesFragment.accountKeys
}
override val sinceIds: Array<String?>?
get() {
val result = arrayOfNulls<String>(accountKeys.size)
val hasSinceAccountKeys = accounts.mapNotNull { account ->
when (account?.type) {
AccountType.FANFOU -> {
return@mapNotNull null
}
}
return@mapNotNull account?.key
}.toTypedArray()
val incomingIds = DataStoreUtils.getMessageIds(context, Messages.CONTENT_URI,
hasSinceAccountKeys.toNulls(), false)
val outgoingIds = DataStoreUtils.getMessageIds(context, Messages.CONTENT_URI,
hasSinceAccountKeys.toNulls(), true)
loop@ for (idx in 0..accountKeys.lastIndex) {
}
return result
}
override val hasSinceIds: Boolean = true
override val hasMaxIds: Boolean = false
twitterWrapper.getMessagesAsync(GetMessagesTask.RefreshNewTaskParam(context) {
this@MessagesEntriesFragment.accountKeys
})
return true
}
@ -119,6 +97,13 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
IntentUtils.openUserProfile(context, user, preferences[newDocumentApiKey])
}
@Subscribe
fun onGetMessagesTaskEvent(event: GetMessagesTaskEvent) {
if (!event.running) {
refreshing = false
}
}
private fun showContentOrError() {
val accountKeys = this.accountKeys
if (adapter.itemCount > 0) {
@ -135,4 +120,6 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
showError(R.drawable.ic_info_accounts, getString(R.string.message_toast_no_account_selected))
}
}
}

View File

@ -16,12 +16,15 @@ import org.mariotaku.twidere.extension.model.setFrom
import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails
import org.mariotaku.twidere.model.util.ParcelableMessageUtils
import org.mariotaku.twidere.model.util.ParcelableUserUtils
import org.mariotaku.twidere.model.util.UserKeyUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.content.ContentResolverUtils
/**
@ -46,6 +49,7 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
override fun afterExecute(callback: ((Boolean) -> Unit)?, result: Unit) {
callback?.invoke(true)
bus.post(GetMessagesTaskEvent(Messages.CONTENT_URI, false, null))
}
private fun getMessages(microBlog: MicroBlog, details: AccountDetails, param: RefreshTaskParam, index: Int): GetMessagesData {
@ -86,7 +90,7 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
if (maxId != null) {
maxId(maxId)
}
if (sinceIds != null) {
if (sinceId != null) {
sinceId(sinceId)
}
})
@ -111,8 +115,8 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
received.forEach {
conversationIds.add(ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId))
}
received.forEach {
conversationIds.add(ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId))
sent.forEach {
conversationIds.add(ParcelableMessageUtils.outgoingConversationId(it.senderId, it.recipientId))
}
conversations.addLocalConversations(accountKey, conversationIds)
@ -215,5 +219,38 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
val conversations: Collection<ParcelableMessageConversation>,
val messages: Collection<ParcelableMessage>
)
class RefreshNewTaskParam(
val context: Context,
val getAccountKeys: () -> Array<UserKey>
) : SimpleRefreshTaskParam() {
private val accounts by lazy {
AccountUtils.getAllAccountDetails(AccountManager.get(context), accountKeys, false)
}
override val accountKeys: Array<UserKey>
get() = getAccountKeys()
override val sinceIds: Array<String?>?
get() {
val keys = accounts.map { account ->
when (account?.type) {
AccountType.FANFOU -> {
return@map null
}
}
return@map account?.key
}.toTypedArray()
val incomingIds = DataStoreUtils.getNewestMessageIds(context, Messages.CONTENT_URI,
keys, false)
val outgoingIds = DataStoreUtils.getNewestMessageIds(context, Messages.CONTENT_URI,
keys, true)
return incomingIds + outgoingIds
}
override val hasSinceIds: Boolean = true
override val hasMaxIds: Boolean = false
}
}

View File

@ -165,13 +165,8 @@ object DataStoreUtils {
OrderBy(SQLFunctions.MAX(Statuses.STATUS_TIMESTAMP)), null, null)
}
fun getMessageIds(context: Context, uri: Uri, accountKeys: Array<UserKey?>, outgoing: Boolean): Array<String?> {
val having: Expression
if (outgoing) {
having = Expression.equals(Messages.IS_OUTGOING, 1)
} else {
having = Expression.notEquals(Messages.IS_OUTGOING, 1)
}
fun getNewestMessageIds(context: Context, uri: Uri, accountKeys: Array<UserKey?>, outgoing: Boolean): Array<String?> {
val having: Expression = Expression.equals(Messages.IS_OUTGOING, if (outgoing) 1 else 0)
return getStringFieldArray(context, uri, accountKeys, Messages.ACCOUNT_KEY, Messages.MESSAGE_ID,
OrderBy(SQLFunctions.MAX(Messages.LOCAL_TIMESTAMP)), having, null)
}
@ -439,27 +434,27 @@ object DataStoreUtils {
.from(Tables(table, Filters.Sources.TABLE_NAME))
.where(Expression.or(
Expression.likeRaw(Column(Table(table), Activities.STATUS_SOURCE),
"'%>'||" + Filters.Sources.TABLE_NAME + "." + Filters.Sources.VALUE + "||'</a>%'"),
"'%>'||${Filters.Sources.TABLE_NAME}.${Filters.Sources.VALUE}||'</a>%'"),
Expression.likeRaw(Column(Table(table), Activities.STATUS_QUOTE_SOURCE),
"'%>'||" + Filters.Sources.TABLE_NAME + "." + Filters.Sources.VALUE + "||'</a>%'")
"'%>'||${Filters.Sources.TABLE_NAME}.${Filters.Sources.VALUE}||'</a>%'")
))
.union()
.select(Columns(Column(Table(table), Activities._ID)))
.from(Tables(table, Filters.Keywords.TABLE_NAME))
.where(Expression.or(
Expression.likeRaw(Column(Table(table), Activities.STATUS_TEXT_PLAIN),
"'%'||" + Filters.Keywords.TABLE_NAME + "." + Filters.Keywords.VALUE + "||'%'"),
"'%'||${Filters.Keywords.TABLE_NAME}.${Filters.Keywords.VALUE}||'%'"),
Expression.likeRaw(Column(Table(table), Activities.STATUS_QUOTE_TEXT_PLAIN),
"'%'||" + Filters.Keywords.TABLE_NAME + "." + Filters.Keywords.VALUE + "||'%'")
"'%'||${Filters.Keywords.TABLE_NAME}.${Filters.Keywords.VALUE}||'%'")
))
.union()
.select(Columns(Column(Table(table), Activities._ID)))
.from(Tables(table, Filters.Links.TABLE_NAME))
.where(Expression.or(
Expression.likeRaw(Column(Table(table), Activities.STATUS_SPANS),
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'"),
"'%'||${Filters.Links.TABLE_NAME}.${Filters.Links.VALUE}||'%'"),
Expression.likeRaw(Column(Table(table), Activities.STATUS_QUOTE_SPANS),
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'")
"'%'||${Filters.Links.TABLE_NAME}.${Filters.Links.VALUE}||'%'")
))
val filterExpression = Expression.or(
Expression.notIn(Column(Table(table), Activities._ID), filteredIdsQueryBuilder.build()),
@ -626,36 +621,36 @@ object DataStoreUtils {
}
@SuppressLint("Recycle")
private fun <T> getFieldArray(context: Context, uri: Uri,
keys: Array<UserKey?>, keyField: String,
valueField: String, sortExpression: OrderBy?,
extraHaving: Expression?, extraHavingArgs: Array<String>?,
creator: FieldArrayCreator<T>): T {
private fun <T> getFieldArray(
context: Context, uri: Uri,
keys: Array<UserKey?>, keyField: String,
valueField: String, sortExpression: OrderBy?,
extraWhere: Expression?, extraWhereArgs: Array<String>?,
creator: FieldArrayCreator<T>
): T {
val resolver = context.contentResolver
val resultArray = creator.newArray(keys.size)
val nonNullKeys = keys.mapNotNull { it?.toString() }.toTypedArray()
val tableName = getTableNameByUri(uri) ?: throw NullPointerException()
val having: Expression
if (extraHaving != null) {
having = Expression.and(extraHaving, Expression.inArgs(keyField, nonNullKeys.size))
val having = Expression.inArgs(keyField, nonNullKeys.size)
val bindingArgs: Array<String>
if (extraWhereArgs != null) {
bindingArgs = extraWhereArgs + nonNullKeys
} else {
having = Expression.inArgs(keyField, nonNullKeys.size)
}
val havingArgs: Array<String>
if (extraHavingArgs != null) {
havingArgs = extraHavingArgs + nonNullKeys
} else {
havingArgs = nonNullKeys
bindingArgs = nonNullKeys
}
val builder = SQLQueryBuilder.select(Columns(keyField, valueField))
.from(Table(tableName))
.groupBy(Column(keyField))
.having(having)
builder.from(Table(tableName))
if (extraWhere != null) {
builder.where(extraWhere)
}
builder.groupBy(Column(keyField))
builder.having(having)
if (sortExpression != null) {
builder.orderBy(sortExpression)
}
val rawUri = Uri.withAppendedPath(TwidereDataStore.CONTENT_URI_RAW_QUERY, builder.buildSQL())
resolver.query(rawUri, null, null, havingArgs, null)?.useCursor { cur ->
resolver.query(rawUri, null, null, bindingArgs, null)?.useCursor { cur ->
cur.moveToFirst()
while (!cur.isAfterLast) {
val string = cur.getString(0)

View File

@ -70,8 +70,10 @@ class TaskServiceRunner(
}
ACTION_REFRESH_DIRECT_MESSAGES -> {
val task = GetMessagesTask(context)
task.params = AutoRefreshTaskParam(context, AccountPreferences::isAutoRefreshDirectMessagesEnabled) { accountKeys ->
arrayOfNulls(accountKeys.size)
task.params = GetMessagesTask.RefreshNewTaskParam(context) {
AccountPreferences.getAccountPreferences(context, DataStoreUtils.getAccountKeys(context)).filter {
it.isAutoRefreshEnabled && it.isAutoRefreshDirectMessagesEnabled
}.map(AccountPreferences::getAccountKey).toTypedArray()
}
return task
}