diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/model/DeletionEvent.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/model/DeletionEvent.java index d2505fdf6..9edc60542 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/model/DeletionEvent.java +++ b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/model/DeletionEvent.java @@ -9,7 +9,7 @@ import com.bluelinelabs.logansquare.annotation.JsonObject; @JsonObject public class DeletionEvent { - @JsonField(name = "id") + @JsonField(name = {"id", "id_str"}) String id; @JsonField(name = "user_id") String userId; diff --git a/twidere/src/androidTest/kotlin/org/mariotaku/twidere/model/ItemCountsTest.kt b/twidere/src/androidTest/kotlin/org/mariotaku/twidere/model/ItemCountsTest.kt new file mode 100644 index 000000000..005431127 --- /dev/null +++ b/twidere/src/androidTest/kotlin/org/mariotaku/twidere/model/ItemCountsTest.kt @@ -0,0 +1,44 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.model + +import org.junit.Assert +import org.junit.Test + +/** + * Created by mariotaku on 2017/3/13. + */ +class ItemCountsTest { + @Test + fun getItemCountIndex() { + val counts = ItemCounts(3) + counts[0] = 2 + counts[1] = 3 + counts[2] = 3 + + Assert.assertEquals(0, counts.getItemCountIndex(1)) + Assert.assertEquals(1, counts.getItemCountIndex(2)) + Assert.assertEquals(1, counts.getItemCountIndex(4)) + Assert.assertEquals(2, counts.getItemCountIndex(7)) + Assert.assertEquals(-1, counts.getItemCountIndex(10)) + Assert.assertEquals(-1, counts.getItemCountIndex(-1)) + } + +} \ No newline at end of file diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/ExtendedDividerItemDecoration.java similarity index 93% rename from twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java rename to twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/ExtendedDividerItemDecoration.java index 204005af4..5e5ae3ce6 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/DividerItemDecoration.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/decorator/ExtendedDividerItemDecoration.java @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.support.annotation.IntRange; import android.support.v4.view.ViewCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -28,7 +29,7 @@ import android.support.v7.widget.RecyclerView.State; import android.support.v7.widget.TintTypedArray; import android.view.View; -public class DividerItemDecoration extends RecyclerView.ItemDecoration { +public class ExtendedDividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider @@ -45,7 +46,8 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { private Padding mPadding; private int mDecorationStart = -1, mDecorationEnd = -1, mDecorationEndOffset; - public DividerItemDecoration(Context context, int orientation) { + @SuppressWarnings("RestrictedApi") + public ExtendedDividerItemDecoration(Context context, int orientation) { final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, ATTRS); mDivider = a.getDrawable(0); a.recycle(); @@ -106,7 +108,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final int childPos = parent.getChildAdapterPosition(child); - if (!isDividerEnabled(childPos)) continue; + if (childPos < 0 || !isDividerEnabled(childPos)) continue; final int start = getDecorationStart(), end = getDecorationEnd(parent); if (start >= 0 && childPos < start || end >= 0 && childPos > end) continue; final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child @@ -137,8 +139,8 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final int childPos = parent.getChildAdapterPosition(child); + if (childPos < 0 || !isDividerEnabled(childPos)) continue; final int start = getDecorationStart(), end = getDecorationEnd(parent); - if (!isDividerEnabled(childPos)) continue; if (start >= 0 && childPos < start || end >= 0 && childPos > end) continue; final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); @@ -156,7 +158,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { if (mDivider == null) return; final int childPos = parent.getChildAdapterPosition(view); - if (!isDividerEnabled(childPos)) return; + if (childPos < 0 || !isDividerEnabled(childPos)) return; final int start = getDecorationStart(), end = getDecorationEnd(parent); if (start >= 0 && childPos < start || end >= 0 && childPos > end) { outRect.setEmpty(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java index 2f1a0acea..5e954ee59 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java @@ -31,7 +31,7 @@ import org.mariotaku.chameleon.Chameleon; import org.mariotaku.chameleon.ChameleonUtils; import org.mariotaku.chameleon.ChameleonView; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration; +import org.mariotaku.twidere.adapter.decorator.ExtendedDividerItemDecoration; import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.view.iface.PagerIndicator; @@ -47,7 +47,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C private final int mStripHeight; private final TabPagerIndicatorAdapter mIndicatorAdapter; private final TabLayoutManager mLayoutManager; - private final DividerItemDecoration mItemDecoration; + private final ExtendedDividerItemDecoration mItemDecoration; private ViewPager mViewPager; private PagerAdapter mPagerProvider; @@ -61,7 +61,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR); final Resources res = getResources(); mIndicatorAdapter = new TabPagerIndicatorAdapter(this); - mItemDecoration = new DividerItemDecoration(context, HORIZONTAL); + mItemDecoration = new ExtendedDividerItemDecoration(context, HORIZONTAL); mStripHeight = res.getDimensionPixelSize(R.dimen.element_spacing_small); setOverScrollMode(OVER_SCROLL_NEVER); setHorizontalScrollBarEnabled(false); diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt index ccd9f7421..25b8e4b1d 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt @@ -89,7 +89,7 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF entriesList.onItemClickListener = this if (savedInstanceState == null) { - val initialTag = intent.data?.path + val initialTag = intent.data?.authority var initialItem = -1 var firstEntry = -1 for (i in 0 until entriesAdapter.count) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/ParcelableActivitiesAdapter.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/ParcelableActivitiesAdapter.kt index 94da6c0b2..6d29dad03 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/ParcelableActivitiesAdapter.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/ParcelableActivitiesAdapter.kt @@ -258,7 +258,7 @@ class ParcelableActivitiesAdapter( if (isGapItem(position)) { return ITEM_VIEW_TYPE_GAP } - val activity = getActivity(position) + val activity = getActivity(position, false) when (activity.action) { Activity.Action.MENTION -> { if (ArrayUtils.isEmpty(activity.target_object_statuses)) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/GlideExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/GlideExtensions.kt index 0d41c4fab..413f24e02 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/GlideExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/GlideExtensions.kt @@ -140,6 +140,7 @@ internal inline fun configureLoadProfileImage(context: Context, @ImageShapeS ): DrawableRequestBuilder { val builder = create() builder.diskCacheStrategy(DiskCacheStrategy.RESULT) + builder.centerCrop() builder.dontAnimate() when (shapeStyle) { ImageShapeStyle.SHAPE_CIRCLE -> { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt index 32c11b0fd..26c049099 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt @@ -48,7 +48,7 @@ import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_ import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_VIEW_TYPE_STATUS import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_VIEW_TYPE_STUB import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_VIEW_TYPE_TITLE_SUMMARY -import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration +import org.mariotaku.twidere.adapter.decorator.ExtendedDividerItemDecoration import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter import org.mariotaku.twidere.annotation.ReadPositionTag import org.mariotaku.twidere.constant.IntentConstants.* @@ -543,9 +543,10 @@ abstract class AbsActivitiesFragment protected constructor() : override fun createItemDecoration(context: Context, recyclerView: RecyclerView, layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? { - val itemDecoration = object : DividerItemDecoration(context, + val itemDecoration = object : ExtendedDividerItemDecoration(context, (recyclerView.layoutManager as LinearLayoutManager).orientation) { override fun isDividerEnabled(childPos: Int): Boolean { + if (childPos >= layoutManager.itemCount || childPos < 0) return false when (adapter.getItemViewType(childPos)) { ITEM_VIEW_TYPE_STATUS, ITEM_VIEW_TYPE_TITLE_SUMMARY, ITEM_VIEW_TYPE_GAP, ITEM_VIEW_TYPE_STUB -> { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentListRecyclerViewFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentListRecyclerViewFragment.kt index a8efae333..9310191df 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentListRecyclerViewFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsContentListRecyclerViewFragment.kt @@ -26,7 +26,7 @@ import android.support.v7.widget.RecyclerView import org.mariotaku.ktextension.contains import org.mariotaku.twidere.adapter.LoadMoreSupportAdapter -import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration +import org.mariotaku.twidere.adapter.decorator.ExtendedDividerItemDecoration import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition @@ -39,12 +39,12 @@ abstract class AbsContentListRecyclerViewFragment? - get() = getNewestActivityIds(accountKeys) + get() = DataStoreUtils.getNewestActivityMaxPositions(context, contentUri, + accountKeys.toNulls()) override val sinceSortIds: LongArray? - get() { - val context = context ?: return null - return DataStoreUtils.getNewestActivityMaxSortPositions(context, - contentUri, accountKeys.toNulls()) - } + get() = DataStoreUtils.getNewestActivityMaxSortPositions(context, contentUri, + accountKeys.toNulls()) override val hasSinceIds: Boolean get() = true @@ -198,11 +196,6 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() { return DataStoreUtils.buildActivityFilterWhereClause(table, null) } - protected fun getNewestActivityIds(accountKeys: Array): Array? { - val context = context ?: return null - return DataStoreUtils.getNewestActivityMaxPositions(context, contentUri, accountKeys.toNulls()) - } - protected abstract val notificationType: Int override fun setUserVisibleHint(isVisibleToUser: Boolean) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/ParcelableUsersFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/ParcelableUsersFragment.kt index 403e63a77..8c6a440aa 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/ParcelableUsersFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/ParcelableUsersFragment.kt @@ -34,7 +34,7 @@ import org.mariotaku.commons.parcel.ParcelUtils import org.mariotaku.kpreferences.get import org.mariotaku.twidere.R import org.mariotaku.twidere.adapter.ParcelableUsersAdapter -import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration +import org.mariotaku.twidere.adapter.decorator.ExtendedDividerItemDecoration import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter import org.mariotaku.twidere.adapter.iface.IUsersAdapter import org.mariotaku.twidere.adapter.iface.IUsersAdapter.UserClickListener @@ -187,7 +187,7 @@ abstract class ParcelableUsersFragment : AbsContentListRecyclerViewFragment>, OnMediaClickListener, StatusClickListener, KeyboardShortcutCallback, ContentListSupport { - private var mItemDecoration: DividerItemDecoration? = null + private var mItemDecoration: ExtendedDividerItemDecoration? = null override lateinit var adapter: StatusAdapter @@ -2187,7 +2187,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks= statusAdapter.itemCount || childPos < 0) return false diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt index aa359ae06..492692d0c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt @@ -66,9 +66,6 @@ class AccountPreferences(private val context: Context, val accountKey: UserKey) } } - val isAutoRefreshDirectMessagesEnabled: Boolean - get() = preferences.getBoolean(KEY_AUTO_REFRESH_DIRECT_MESSAGES, DEFAULT_AUTO_REFRESH_DIRECT_MESSAGES) - val isAutoRefreshEnabled: Boolean get() = preferences.getBoolean(KEY_AUTO_REFRESH, preferences.getBoolean(KEY_DEFAULT_AUTO_REFRESH, false)) @@ -78,12 +75,24 @@ class AccountPreferences(private val context: Context, val accountKey: UserKey) val isAutoRefreshMentionsEnabled: Boolean get() = preferences.getBoolean(KEY_AUTO_REFRESH_MENTIONS, DEFAULT_AUTO_REFRESH_MENTIONS) + val isAutoRefreshDirectMessagesEnabled: Boolean + get() = preferences.getBoolean(KEY_AUTO_REFRESH_DIRECT_MESSAGES, DEFAULT_AUTO_REFRESH_DIRECT_MESSAGES) + val isAutoRefreshTrendsEnabled: Boolean get() = preferences.getBoolean(KEY_AUTO_REFRESH_TRENDS, DEFAULT_AUTO_REFRESH_TRENDS) val isStreamingEnabled: Boolean get() = preferences.getBoolean(KEY_ENABLE_STREAMING, false) + val isStreamHomeTimelineEnabled: Boolean + get() = preferences.getBoolean("stream_home_timeline", true) + + val isStreamInteractionsEnabled: Boolean + get() = preferences.getBoolean("stream_interactions", true) + + val isStreamDirectMessagesEnabled: Boolean + get() = preferences.getBoolean("stream_direct_messages", true) + val isDirectMessagesNotificationEnabled: Boolean get() = preferences.getBoolean(KEY_DIRECT_MESSAGES_NOTIFICATION, DEFAULT_DIRECT_MESSAGES_NOTIFICATION) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/ItemCounts.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/ItemCounts.kt index 28accdbcb..a97b4c4b9 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/ItemCounts.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/ItemCounts.kt @@ -8,6 +8,7 @@ class ItemCounts(counts: Int) { private val data: IntArray = IntArray(counts) fun getItemCountIndex(itemPosition: Int): Int { + if (itemPosition < 0) return -1 var sum = 0 data.forEachIndexed { i, num -> sum += num diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt index 93b5c4a44..7ca7ea99c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt @@ -61,7 +61,7 @@ class ConnectivityStateReceiver : BroadcastReceiver() { appContext.startService(Intent(appContext, UploadLogsService::class.java)) } } - StreamingService.startOrStopService(context) + StreamingService.startOrStopService(appContext) } companion object { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt index eb82f9f8c..2d8189d51 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt @@ -7,6 +7,8 @@ import android.content.Context import android.content.Intent import android.os.Handler import android.os.Looper +import android.support.annotation.UiThread +import android.support.annotation.WorkerThread import android.support.v4.app.NotificationCompat import android.support.v4.net.ConnectivityManagerCompat import org.apache.commons.lang3.concurrent.BasicThreadFactory @@ -18,9 +20,9 @@ import org.mariotaku.library.objectcursor.ObjectCursor import org.mariotaku.microblog.library.MicroBlogException import org.mariotaku.microblog.library.twitter.TwitterUserStream import org.mariotaku.microblog.library.twitter.annotation.StreamWith -import org.mariotaku.microblog.library.twitter.model.Activity -import org.mariotaku.microblog.library.twitter.model.DirectMessage -import org.mariotaku.microblog.library.twitter.model.Status +import org.mariotaku.microblog.library.twitter.model.* +import org.mariotaku.sqliteqb.library.Columns +import org.mariotaku.sqliteqb.library.Expression import org.mariotaku.twidere.R import org.mariotaku.twidere.TwidereConstants.LOGTAG import org.mariotaku.twidere.annotation.AccountType @@ -100,28 +102,34 @@ class StreamingService : BaseService() { if (!activityTracker.isHomeActivityLaunched) { return false } + // Quit if no connection + if (connectivityManager.activeNetworkInfo?.isAvailable != true) { + return false + } + // Quit if connection metered (with preference) val isNetworkMetered = ConnectivityManagerCompat.isActiveNetworkMetered(connectivityManager) if (preferences[streamingNonMeteredNetworkKey] && isNetworkMetered) { return false } + // Quit if not charging (with preference) val isCharging = Utils.isCharging(this) if (preferences[streamingPowerSavingKey] && !isCharging) { return false } - if (updateStreamingInstances()) { - showNotification() - return true - } else { + // Quit if no streaming instance available + if (!updateStreamingInstances()) { return false } + showNotification() + return true } private fun updateStreamingInstances(): Boolean { val am = AccountManager.get(this) val supportedAccounts = AccountUtils.getAllAccountDetails(am, true).filter { it.isStreamingSupported } - val enabledPrefs = supportedAccounts.map { AccountPreferences(this, it.key) } + val supportedPrefs = supportedAccounts.map { AccountPreferences(this, it.key) } val enabledAccounts = supportedAccounts.filter { account -> - return@filter enabledPrefs.any { + return@filter supportedPrefs.any { account.key == it.accountKey && it.isStreamingEnabled } } @@ -138,7 +146,9 @@ class StreamingService : BaseService() { enabledAccounts.forEach { account -> val existing = submittedTasks[account.key] if (existing == null || existing.cancelled) { - val runnable = account.newStreamingRunnable() ?: return@forEach + val runnable = newStreamingRunnable(account, supportedPrefs.first { + it.accountKey == account.key + }) ?: return@forEach threadPoolExecutor.submit(runnable) submittedTasks[account.key] = runnable } @@ -170,16 +180,20 @@ class StreamingService : BaseService() { } - private fun AccountDetails.newStreamingRunnable(): StreamingRunnable<*>? { - when (type) { + private fun newStreamingRunnable(account: AccountDetails, preferences: AccountPreferences): StreamingRunnable<*>? { + when (account.type) { AccountType.TWITTER -> { - return TwitterStreamingRunnable(this@StreamingService, handler, this) + return TwitterStreamingRunnable(this, handler, account, preferences) } } return null } - internal abstract class StreamingRunnable(val context: Context, val account: AccountDetails) : Runnable { + internal abstract class StreamingRunnable( + val context: Context, + val account: AccountDetails, + val preferences: AccountPreferences + ) : Runnable { var cancelled: Boolean = false private set @@ -210,8 +224,12 @@ class StreamingService : BaseService() { abstract fun onCancelled() } - internal class TwitterStreamingRunnable(context: Context, val handler: Handler, account: AccountDetails) : - StreamingRunnable(context, account) { + internal class TwitterStreamingRunnable( + context: Context, + val handler: Handler, + account: AccountDetails, + preferences: AccountPreferences + ) : StreamingRunnable(context, account, preferences) { private val profileImageSize = context.getString(R.string.profile_image_size) private val isOfficial = account.isOfficial(context) @@ -241,6 +259,10 @@ class StreamingService : BaseService() { } override fun onHomeTimeline(status: Status): Boolean { + if (!preferences.isStreamHomeTimelineEnabled) { + homeInsertGap = true + return false + } val parcelableStatus = ParcelableStatusUtils.fromStatus(status, account.key, homeInsertGap, profileImageSize) @@ -264,10 +286,14 @@ class StreamingService : BaseService() { } override fun onActivityAboutMe(activity: Activity): Boolean { + if (!preferences.isStreamInteractionsEnabled) { + interactionsInsertGap = true + return false + } if (isOfficial) { // Wait for 30 seconds to avoid rate limit if (canGetInteractions) { - getInteractions() + handler.post { getInteractions() } canGetInteractions = false handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30)) } @@ -283,9 +309,13 @@ class StreamingService : BaseService() { return true } + @WorkerThread override fun onDirectMessage(directMessage: DirectMessage): Boolean { + if (!preferences.isStreamDirectMessagesEnabled) { + return false + } if (canGetMessages) { - getMessages() + handler.post { getMessages() } canGetMessages = false val timeout = TimeUnit.SECONDS.toMillis(if (isOfficial) 30 else 90) handler.postDelayed(messagesTimeoutRunnable, timeout) @@ -298,6 +328,19 @@ class StreamingService : BaseService() { return true } + override fun onStatusDeleted(event: DeletionEvent): Boolean { + val deleteWhere = Expression.and(Expression.likeRaw(Columns.Column(Statuses.ACCOUNT_KEY), "%@||?"), + Expression.equalsArgs(Columns.Column(Statuses.STATUS_ID))).sql + val deleteWhereArgs = arrayOf(account.key.host, event.id) + context.contentResolver.delete(Statuses.CONTENT_URI, deleteWhere, deleteWhereArgs) + return true + } + + override fun onUnhandledEvent(obj: TwitterStreamObject, json: String) { + DebugLog.w(LOGTAG, msg = "Unhandled event ${obj.determine()} for ${account.key}: $json") + } + + @UiThread private fun getInteractions() { val task = GetActivitiesAboutMeTask(context) task.params = object : SimpleRefreshTaskParam() { @@ -317,6 +360,7 @@ class StreamingService : BaseService() { TaskStarter.execute(task) } + @UiThread private fun getMessages() { val task = GetMessagesTask(context) task.params = object : GetMessagesTask.RefreshMessagesTaskParam(context) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt index 862322233..1e94f274b 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentNotificationManager.kt @@ -160,7 +160,7 @@ class ContentNotificationManager( Expression.equalsArgs(Activities.ACCOUNT_KEY), Expression.greaterThanArgs(Activities.POSITION_KEY) ).sql - val whereArgs = arrayOf(accountKey.toString(), "0") + val whereArgs = arrayOf(accountKey.toString(), position.toString()) @SuppressLint("Recycle") val c = cr.query(Activities.AboutMe.CONTENT_URI, Activities.COLUMNS, where, whereArgs, OrderBy(Activities.TIMESTAMP, false).sql) ?: return diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt index 715895868..fc7c5cba7 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt @@ -19,6 +19,7 @@ package org.mariotaku.twidere.util.streaming +import android.support.annotation.WorkerThread import org.mariotaku.microblog.library.twitter.callback.SimpleUserStreamCallback import org.mariotaku.microblog.library.twitter.model.* import java.util.* @@ -26,7 +27,7 @@ import java.util.* /** * Created by mariotaku on 2017/3/10. */ - +@WorkerThread abstract class TwitterTimelineStreamCallback(val accountId: String) : SimpleUserStreamCallback() { private val friends = mutableSetOf() @@ -130,9 +131,12 @@ abstract class TwitterTimelineStreamCallback(val accountId: String) : SimpleUser return false } + @WorkerThread protected abstract fun onHomeTimeline(status: Status): Boolean + @WorkerThread protected abstract fun onActivityAboutMe(activity: Activity): Boolean + @WorkerThread override abstract fun onDirectMessage(directMessage: DirectMessage): Boolean } diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index aa93f8986..2d772767f 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -1039,6 +1039,10 @@ Retweet + Home + Interactions + Messages + Streaming Style diff --git a/twidere/src/main/res/xml/preferences_account_streaming.xml b/twidere/src/main/res/xml/preferences_account_streaming.xml index a6bfcf7f5..24f478fed 100644 --- a/twidere/src/main/res/xml/preferences_account_streaming.xml +++ b/twidere/src/main/res/xml/preferences_account_streaming.xml @@ -17,9 +17,21 @@ ~ You should have received a copy of the GNU General Public License ~ along with this program. If not, see . --> - + + + + \ No newline at end of file