fixed interactions notifications unread

improved streaming refresh
This commit is contained in:
Mariotaku Lee 2017-03-13 23:00:04 +08:00
parent 1b542cea6c
commit 9506fa704e
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
21 changed files with 174 additions and 59 deletions

View File

@ -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;

View File

@ -0,0 +1,44 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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))
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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) {

View File

@ -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)) {

View File

@ -140,6 +140,7 @@ internal inline fun <T> configureLoadProfileImage(context: Context, @ImageShapeS
): DrawableRequestBuilder<T> {
val builder = create()
builder.diskCacheStrategy(DiskCacheStrategy.RESULT)
builder.centerCrop()
builder.dontAnimate()
when (shapeStyle) {
ImageShapeStyle.SHAPE_CIRCLE -> {

View File

@ -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 -> {

View File

@ -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<A : LoadMoreSupportAdapter<Rec
override fun createItemDecoration(context: Context, recyclerView: RecyclerView,
layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? {
return DividerItemDecoration(context, layoutManager.orientation)
return ExtendedDividerItemDecoration(context, layoutManager.orientation)
}
override fun setLoadMoreIndicatorPosition(@IndicatorPosition position: Long) {
val decor = itemDecoration
if (decor is DividerItemDecoration) {
if (decor is ExtendedDividerItemDecoration) {
decor.setDecorationStart(if (ILoadMoreSupportAdapter.START in position) 1 else 0)
decor.setDecorationEndOffset(if (ILoadMoreSupportAdapter.END in position) 1 else 0)
}

View File

@ -44,7 +44,7 @@ import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
import org.mariotaku.twidere.activity.AccountSelectorActivity
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter
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.annotation.Referral
@ -402,7 +402,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
}
override fun createItemDecoration(context: Context, recyclerView: RecyclerView, layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? {
val itemDecoration = DividerItemDecoration(context, (recyclerView.layoutManager as LinearLayoutManager).orientation)
val itemDecoration = ExtendedDividerItemDecoration(context, (recyclerView.layoutManager as LinearLayoutManager).orientation)
val res = context.resources
if (adapter.profileImageEnabled) {
val decorPaddingLeft = res.getDimensionPixelSize(R.dimen.element_spacing_normal) * 2 + res.getDimensionPixelSize(R.dimen.icon_size_status_profile_image)

View File

@ -175,14 +175,12 @@ abstract class CursorActivitiesFragment : AbsActivitiesFragment() {
}
override val sinceIds: Array<String?>?
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<UserKey>): Array<String?>? {
val context = context ?: return null
return DataStoreUtils.getNewestActivityMaxPositions(context, contentUri, accountKeys.toNulls())
}
protected abstract val notificationType: Int
override fun setUserVisibleHint(isVisibleToUser: Boolean) {

View File

@ -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<Parc
override fun createItemDecoration(context: Context, recyclerView: RecyclerView,
layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? {
val itemDecoration = DividerItemDecoration(context,
val itemDecoration = ExtendedDividerItemDecoration(context,
(recyclerView.layoutManager as LinearLayoutManager).orientation)
val res = context.resources
if (adapter.profileImageEnabled) {

View File

@ -83,7 +83,7 @@ import org.mariotaku.twidere.activity.ColorPickerDialogActivity
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter
import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter
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.IGapSupportedAdapter
import org.mariotaku.twidere.adapter.iface.IItemCountsAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
@ -131,7 +131,7 @@ import java.util.*
class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<ParcelableStatus>>,
OnMediaClickListener, StatusClickListener, KeyboardShortcutCallback,
ContentListSupport<StatusFragment.StatusAdapter> {
private var mItemDecoration: DividerItemDecoration? = null
private var mItemDecoration: ExtendedDividerItemDecoration? = null
override lateinit var adapter: StatusAdapter
@ -2187,7 +2187,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
context: Context,
private val statusAdapter: StatusAdapter,
orientation: Int
) : DividerItemDecoration(context, orientation) {
) : ExtendedDividerItemDecoration(context, orientation) {
override fun isDividerEnabled(childPos: Int): Boolean {
if (childPos >= statusAdapter.itemCount || childPos < 0) return false

View File

@ -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)

View File

@ -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

View File

@ -61,7 +61,7 @@ class ConnectivityStateReceiver : BroadcastReceiver() {
appContext.startService(Intent(appContext, UploadLogsService::class.java))
}
}
StreamingService.startOrStopService(context)
StreamingService.startOrStopService(appContext)
}
companion object {

View File

@ -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<T>(val context: Context, val account: AccountDetails) : Runnable {
internal abstract class StreamingRunnable<T>(
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<TwitterUserStream>(context, account) {
internal class TwitterStreamingRunnable(
context: Context,
val handler: Handler,
account: AccountDetails,
preferences: AccountPreferences
) : StreamingRunnable<TwitterUserStream>(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) {

View File

@ -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

View File

@ -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<String>()
@ -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
}

View File

@ -1039,6 +1039,10 @@
<!-- [noun] Accessibility label for retweet icon -->
<string name="status_type_retweet">Retweet</string>
<string name="stream_type_home">Home</string>
<string name="stream_type_interactions">Interactions</string>
<string name="stream_type_messages">Messages</string>
<string name="streaming">Streaming</string>
<string name="style">Style</string>

View File

@ -17,9 +17,21 @@
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<!--suppress AndroidElementNotAllowed -->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/title_streaming">
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="stream_home_timeline"
android:title="@string/stream_type_home"/>
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="stream_interactions"
android:title="@string/stream_type_interactions"/>
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="stream_direct_messages"
android:title="@string/stream_type_messages"/>
</PreferenceScreen>