implemented mastodon interactions timeline
This commit is contained in:
parent
dad16bdc3b
commit
d1b175b524
|
@ -18,9 +18,18 @@
|
||||||
|
|
||||||
package org.mariotaku.microblog.library.mastodon.api;
|
package org.mariotaku.microblog.library.mastodon.api;
|
||||||
|
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException;
|
||||||
|
import org.mariotaku.microblog.library.mastodon.model.LinkHeaderList;
|
||||||
|
import org.mariotaku.microblog.library.mastodon.model.Notification;
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Paging;
|
||||||
|
import org.mariotaku.restfu.annotation.method.GET;
|
||||||
|
import org.mariotaku.restfu.annotation.param.Query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 2017/4/17.
|
* Created by mariotaku on 2017/4/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface NotificationsResources {
|
public interface NotificationsResources {
|
||||||
|
@GET("/v1/notifications")
|
||||||
|
LinkHeaderList<Notification> getNotifications(@Query Paging paging) throws MicroBlogException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
package org.mariotaku.microblog.library.mastodon.model;
|
package org.mariotaku.microblog.library.mastodon.model;
|
||||||
|
|
||||||
|
import android.support.annotation.StringDef;
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||||
|
|
||||||
|
@ -36,7 +38,8 @@ public class Notification {
|
||||||
@JsonField(name = "id")
|
@JsonField(name = "id")
|
||||||
String id;
|
String id;
|
||||||
/**
|
/**
|
||||||
* One of: {@code mention}, {@code reblog}, {@code favourite}, {@code follow}
|
* One of: {@link Type#MENTION}, {@link Type#REBLOG}, {@link Type#FAVOURITE},
|
||||||
|
* {@link Type#FOLLOW}
|
||||||
*/
|
*/
|
||||||
@JsonField(name = "type")
|
@JsonField(name = "type")
|
||||||
String type;
|
String type;
|
||||||
|
@ -86,4 +89,9 @@ public class Notification {
|
||||||
", status=" + status +
|
", status=" + status +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@StringDef({Type.MENTION, Type.REBLOG, Type.FAVOURITE, Type.FOLLOW})
|
||||||
|
public @interface Type {
|
||||||
|
String MENTION = "mention", REBLOG = "reblog", FAVOURITE = "favourite", FOLLOW = "follow";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
|
||||||
@ParcelableThisPlease
|
@ParcelableThisPlease
|
||||||
@JsonField(name = "source_ids", typeConverter = UserKeysConverter.class)
|
@JsonField(name = "source_ids", typeConverter = UserKeysConverter.class)
|
||||||
@CursorField(value = Activities.SOURCE_IDS, converter = UserKeysCursorFieldConverter.class)
|
@CursorField(value = Activities.SOURCE_IDS, converter = UserKeysCursorFieldConverter.class)
|
||||||
public UserKey[] source_ids;
|
public UserKey[] source_keys;
|
||||||
|
|
||||||
@ParcelableThisPlease
|
@ParcelableThisPlease
|
||||||
@JsonField(name = "sources")
|
@JsonField(name = "sources")
|
||||||
|
@ -215,7 +215,7 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
|
||||||
", max_position='" + max_position + '\'' +
|
", max_position='" + max_position + '\'' +
|
||||||
", min_position='" + min_position + '\'' +
|
", min_position='" + min_position + '\'' +
|
||||||
", action='" + action + '\'' +
|
", action='" + action + '\'' +
|
||||||
", source_ids=" + Arrays.toString(source_ids) +
|
", source_ids=" + Arrays.toString(source_keys) +
|
||||||
", sources=" + Arrays.toString(sources) +
|
", sources=" + Arrays.toString(sources) +
|
||||||
", target_users=" + Arrays.toString(target_users) +
|
", target_users=" + Arrays.toString(target_users) +
|
||||||
", target_statuses=" + Arrays.toString(target_statuses) +
|
", target_statuses=" + Arrays.toString(target_statuses) +
|
||||||
|
|
|
@ -34,12 +34,12 @@ import org.mariotaku.microblog.library.twitter.model.Activity
|
||||||
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
||||||
import org.mariotaku.microblog.library.twitter.model.Status
|
import org.mariotaku.microblog.library.twitter.model.Status
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
|
import org.mariotaku.twidere.extension.model.api.microblog.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
import org.mariotaku.twidere.model.ActivityTitleSummaryMessage
|
import org.mariotaku.twidere.model.ActivityTitleSummaryMessage
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
|
||||||
import org.mariotaku.twidere.util.UserColorNameManager
|
import org.mariotaku.twidere.util.UserColorNameManager
|
||||||
import org.mariotaku.twidere.util.dagger.DependencyHolder
|
import org.mariotaku.twidere.util.dagger.DependencyHolder
|
||||||
import org.mariotaku.twidere.util.streaming.FanfouTimelineStreamCallback
|
import org.mariotaku.twidere.util.streaming.FanfouTimelineStreamCallback
|
||||||
|
@ -118,8 +118,7 @@ class UserStreamDumperPlugin(val context: Context) : DumperPlugin {
|
||||||
if (verboseMode) {
|
if (verboseMode) {
|
||||||
dumpContext.stdout.println("Activity: @${activity.toString().trim('\n')}")
|
dumpContext.stdout.println("Activity: @${activity.toString().trim('\n')}")
|
||||||
} else {
|
} else {
|
||||||
val pActivity = ParcelableActivityUtils.fromActivity(activity, account.key,
|
val pActivity = activity.toParcelable(account.key, account.type)
|
||||||
account.type)
|
|
||||||
val message = ActivityTitleSummaryMessage.get(context, manager, pActivity,
|
val message = ActivityTitleSummaryMessage.get(context, manager, pActivity,
|
||||||
pActivity.sources, 0, true, true)
|
pActivity.sources, 0, true, true)
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
|
@ -173,8 +172,7 @@ class UserStreamDumperPlugin(val context: Context) : DumperPlugin {
|
||||||
|
|
||||||
override fun onActivityAboutMe(activity: Activity): Boolean {
|
override fun onActivityAboutMe(activity: Activity): Boolean {
|
||||||
if (!includeInteractions && includeTimeline) return true
|
if (!includeInteractions && includeTimeline) return true
|
||||||
val pActivity = ParcelableActivityUtils.fromActivity(activity, account.key,
|
val pActivity = activity.toParcelable(account.key, account.type)
|
||||||
account.type)
|
|
||||||
val message = ActivityTitleSummaryMessage.get(context, manager, pActivity, pActivity.sources, 0,
|
val message = ActivityTitleSummaryMessage.get(context, manager, pActivity, pActivity.sources, 0,
|
||||||
true, true)
|
true, true)
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.extension.model.api.mastodon
|
||||||
|
|
||||||
|
import org.mariotaku.ktextension.mapToArray
|
||||||
|
import org.mariotaku.microblog.library.mastodon.model.Notification
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Activity
|
||||||
|
import org.mariotaku.twidere.model.ParcelableActivity
|
||||||
|
import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2017/4/22.
|
||||||
|
*/
|
||||||
|
fun Notification.toParcelable(accountKey: UserKey): ParcelableActivity {
|
||||||
|
val result = ParcelableActivity()
|
||||||
|
result.account_key = accountKey
|
||||||
|
result.timestamp = createdAt.time
|
||||||
|
result.min_position = id
|
||||||
|
result.max_position = id
|
||||||
|
result.min_sort_position = result.timestamp
|
||||||
|
result.max_sort_position = result.timestamp
|
||||||
|
result.sources = toSources(accountKey)
|
||||||
|
when (type) {
|
||||||
|
Notification.Type.MENTION -> {
|
||||||
|
result.action = Activity.Action.MENTION
|
||||||
|
result.target_object_statuses = toStatuses(accountKey)
|
||||||
|
}
|
||||||
|
Notification.Type.REBLOG -> {
|
||||||
|
result.action = Activity.Action.RETWEET
|
||||||
|
result.target_object_statuses = toStatuses(accountKey)
|
||||||
|
}
|
||||||
|
Notification.Type.FAVOURITE -> {
|
||||||
|
result.action = Activity.Action.FAVORITE
|
||||||
|
result.target_statuses = toStatuses(accountKey)
|
||||||
|
}
|
||||||
|
Notification.Type.FOLLOW -> {
|
||||||
|
result.action = Activity.Action.FOLLOW
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
result.action = type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.source_keys = result.sources?.mapToArray { it.key }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Notification.toSources(accountKey: UserKey): Array<ParcelableUser>? {
|
||||||
|
val account = this.account ?: return null
|
||||||
|
return arrayOf(account.toParcelable(accountKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Notification.toStatuses(accountKey: UserKey): Array<ParcelableStatus>? {
|
||||||
|
val status = this.status ?: return null
|
||||||
|
return arrayOf(status.toParcelable(accountKey))
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.extension.model.api.microblog
|
||||||
|
|
||||||
|
import org.mariotaku.ktextension.mapToArray
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Activity
|
||||||
|
import org.mariotaku.twidere.extension.model.toParcelables
|
||||||
|
import org.mariotaku.twidere.model.ParcelableActivity
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2017/4/22.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun Activity.toParcelable(accountKey: UserKey, accountType: String, isGap: Boolean = false,
|
||||||
|
profileImageSize: String = "normal"): ParcelableActivity {
|
||||||
|
val result = ParcelableActivity()
|
||||||
|
result.account_key = accountKey
|
||||||
|
result.timestamp = createdAt.time
|
||||||
|
result.action = action
|
||||||
|
result.max_sort_position = maxSortPosition
|
||||||
|
result.min_sort_position = minSortPosition
|
||||||
|
result.max_position = maxPosition
|
||||||
|
result.min_position = minPosition
|
||||||
|
result.sources = sources?.toParcelables(accountKey, accountType,
|
||||||
|
profileImageSize)
|
||||||
|
result.target_users = targetUsers?.toParcelables(accountKey,
|
||||||
|
accountType, profileImageSize)
|
||||||
|
result.target_user_lists = targetUserLists?.toParcelables(accountKey,
|
||||||
|
profileImageSize)
|
||||||
|
result.target_statuses = targetStatuses?.toParcelables(accountKey,
|
||||||
|
accountType, profileImageSize)
|
||||||
|
result.target_object_statuses = targetObjectStatuses?.toParcelables(accountKey,
|
||||||
|
accountType, profileImageSize)
|
||||||
|
result.target_object_user_lists = targetObjectUserLists?.toParcelables(accountKey,
|
||||||
|
profileImageSize)
|
||||||
|
result.target_object_users = targetObjectUsers?.toParcelables(accountKey, accountType,
|
||||||
|
profileImageSize)
|
||||||
|
result.has_following_source = sources?.fold(false) { folded, item ->
|
||||||
|
if (item.isFollowing == true) {
|
||||||
|
return@fold true
|
||||||
|
}
|
||||||
|
return@fold folded
|
||||||
|
} ?: false
|
||||||
|
result.source_keys = result.sources?.mapToArray { it.key }
|
||||||
|
result.is_gap = isGap
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.task
|
||||||
|
|
||||||
|
data class GetTimelineResult(val exception: Exception?)
|
|
@ -1,7 +1,5 @@
|
||||||
package org.mariotaku.twidere.model.util
|
package org.mariotaku.twidere.model.util
|
||||||
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Activity
|
|
||||||
import org.mariotaku.twidere.extension.model.toParcelables
|
|
||||||
import org.mariotaku.twidere.model.ParcelableActivity
|
import org.mariotaku.twidere.model.ParcelableActivity
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
@ -41,7 +39,7 @@ object ParcelableActivityUtils {
|
||||||
activity.after_filtered_source_ids = list.toTypedArray()
|
activity.after_filtered_source_ids = list.toTypedArray()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
activity.after_filtered_source_ids = activity.source_ids
|
activity.after_filtered_source_ids = activity.source_keys
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,45 +56,5 @@ object ParcelableActivityUtils {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromActivity(activity: Activity, accountKey: UserKey, accountType: String,
|
|
||||||
isGap: Boolean = false, profileImageSize: String = "normal"): ParcelableActivity {
|
|
||||||
val result = ParcelableActivity()
|
|
||||||
result.account_key = accountKey
|
|
||||||
result.timestamp = activity.createdAt.time
|
|
||||||
result.action = activity.action
|
|
||||||
result.max_sort_position = activity.maxSortPosition
|
|
||||||
result.min_sort_position = activity.minSortPosition
|
|
||||||
result.max_position = activity.maxPosition
|
|
||||||
result.min_position = activity.minPosition
|
|
||||||
result.sources = activity.sources?.toParcelables(accountKey, accountType,
|
|
||||||
profileImageSize)
|
|
||||||
result.target_users = activity.targetUsers?.toParcelables(accountKey,
|
|
||||||
accountType, profileImageSize)
|
|
||||||
result.target_user_lists = activity.targetUserLists?.toParcelables(accountKey,
|
|
||||||
profileImageSize)
|
|
||||||
result.target_statuses = activity.targetStatuses?.toParcelables(accountKey,
|
|
||||||
accountType, profileImageSize)
|
|
||||||
result.target_object_statuses = activity.targetObjectStatuses?.toParcelables(accountKey,
|
|
||||||
accountType, profileImageSize)
|
|
||||||
result.target_object_user_lists = activity.targetObjectUserLists?.toParcelables(accountKey,
|
|
||||||
profileImageSize)
|
|
||||||
result.target_object_users = activity.targetObjectUsers?.toParcelables(accountKey, accountType,
|
|
||||||
profileImageSize)
|
|
||||||
result.has_following_source = activity.sources?.fold(false) { folded, item ->
|
|
||||||
if (item.isFollowing == true) {
|
|
||||||
return@fold true
|
|
||||||
}
|
|
||||||
return@fold folded
|
|
||||||
} ?: false
|
|
||||||
if (result.sources != null) {
|
|
||||||
result.source_ids = arrayOfNulls<UserKey>(result.sources.size)
|
|
||||||
for (i in result.sources.indices) {
|
|
||||||
result.source_ids[i] = result.sources[i].key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.is_gap = isGap
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.mariotaku.twidere.constant.streamingEnabledKey
|
||||||
import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey
|
import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey
|
||||||
import org.mariotaku.twidere.constant.streamingPowerSavingKey
|
import org.mariotaku.twidere.constant.streamingPowerSavingKey
|
||||||
import org.mariotaku.twidere.extension.model.*
|
import org.mariotaku.twidere.extension.model.*
|
||||||
|
import org.mariotaku.twidere.extension.model.api.microblog.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||||
import org.mariotaku.twidere.model.*
|
import org.mariotaku.twidere.model.*
|
||||||
import org.mariotaku.twidere.model.pagination.SinceMaxPagination
|
import org.mariotaku.twidere.model.pagination.SinceMaxPagination
|
||||||
|
@ -315,8 +316,8 @@ class StreamingService : BaseService() {
|
||||||
} else {
|
} else {
|
||||||
insertGap = false
|
insertGap = false
|
||||||
}
|
}
|
||||||
val curActivity = ParcelableActivityUtils.fromActivity(activity, account.key,
|
val curActivity = activity.toParcelable(account.key, account.type, insertGap,
|
||||||
account.type, insertGap, profileImageSize)
|
profileImageSize)
|
||||||
curActivity.account_color = account.color
|
curActivity.account_color = account.color
|
||||||
curActivity.position_key = curActivity.timestamp
|
curActivity.position_key = curActivity.timestamp
|
||||||
var updateId = -1L
|
var updateId = -1L
|
||||||
|
|
|
@ -23,12 +23,18 @@ import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import org.mariotaku.microblog.library.MicroBlog
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||||
import org.mariotaku.microblog.library.twitter.model.*
|
import org.mariotaku.microblog.library.twitter.model.*
|
||||||
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.annotation.ReadPositionTag
|
import org.mariotaku.twidere.annotation.ReadPositionTag
|
||||||
|
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||||
|
import org.mariotaku.twidere.extension.model.api.microblog.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.isOfficial
|
import org.mariotaku.twidere.extension.model.isOfficial
|
||||||
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.fragment.InteractionsTimelineFragment
|
import org.mariotaku.twidere.fragment.InteractionsTimelineFragment
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
import org.mariotaku.twidere.model.ParcelableActivity
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
||||||
import org.mariotaku.twidere.util.ErrorInfoStore
|
import org.mariotaku.twidere.util.ErrorInfoStore
|
||||||
|
@ -45,24 +51,38 @@ class GetActivitiesAboutMeTask(context: Context) : GetActivitiesTask(context) {
|
||||||
override val contentUri: Uri
|
override val contentUri: Uri
|
||||||
get() = Activities.AboutMe.CONTENT_URI
|
get() = Activities.AboutMe.CONTENT_URI
|
||||||
|
|
||||||
|
|
||||||
|
private val profileImageSize = context.getString(R.string.profile_image_size)
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
override fun getActivities(twitter: MicroBlog, details: AccountDetails, paging: Paging):
|
override fun getActivities(account: AccountDetails, paging: Paging): List<ParcelableActivity> {
|
||||||
ResponseList<Activity> {
|
when (account.type) {
|
||||||
if (details.isOfficial(context)) {
|
AccountType.MASTODON -> {
|
||||||
return twitter.getActivitiesAboutMe(paging)
|
val mastodon = account.newMicroBlogInstance(context, Mastodon::class.java)
|
||||||
|
return mastodon.getNotifications(paging).map {
|
||||||
|
it.toParcelable(account.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val activities = ResponseList<Activity>()
|
|
||||||
val statuses: ResponseList<Status>
|
|
||||||
when (details.type) {
|
|
||||||
AccountType.FANFOU -> {
|
AccountType.FANFOU -> {
|
||||||
statuses = twitter.getMentions(paging)
|
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||||
|
if (account.isOfficial(context)) {
|
||||||
|
return microBlog.getActivitiesAboutMe(paging).map {
|
||||||
|
it.toParcelable(account.key, account.type, profileImageSize = profileImageSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return microBlog.getMentions(paging).map {
|
||||||
|
InternalActivityCreator.status(it, account.key.id).toParcelable(account.key,
|
||||||
|
account.type, profileImageSize = profileImageSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
statuses = twitter.getMentionsTimeline(paging)
|
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||||
|
return microBlog.getHomeTimeline(paging).map {
|
||||||
|
InternalActivityCreator.status(it, account.key.id).toParcelable(account.key,
|
||||||
|
account.type, profileImageSize = profileImageSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statuses.mapTo(activities) { InternalActivityCreator.status(it, details.key.id) }
|
|
||||||
return activities
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package org.mariotaku.twidere.task.twitter
|
package org.mariotaku.twidere.task.twitter
|
||||||
|
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.annotation.UiThread
|
import android.support.annotation.UiThread
|
||||||
import org.mariotaku.kpreferences.get
|
import org.mariotaku.kpreferences.get
|
||||||
import org.mariotaku.microblog.library.MicroBlog
|
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
import org.mariotaku.microblog.library.twitter.model.Activity
|
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
|
||||||
import org.mariotaku.sqliteqb.library.Expression
|
import org.mariotaku.sqliteqb.library.Expression
|
||||||
import org.mariotaku.twidere.R
|
import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||||
|
@ -20,14 +16,13 @@ import org.mariotaku.twidere.constant.loadItemLimitKey
|
||||||
import org.mariotaku.twidere.extension.model.getMaxId
|
import org.mariotaku.twidere.extension.model.getMaxId
|
||||||
import org.mariotaku.twidere.extension.model.getMaxSortId
|
import org.mariotaku.twidere.extension.model.getMaxSortId
|
||||||
import org.mariotaku.twidere.extension.model.getSinceId
|
import org.mariotaku.twidere.extension.model.getSinceId
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
import org.mariotaku.twidere.model.ParcelableActivity
|
||||||
import org.mariotaku.twidere.model.RefreshTaskParam
|
import org.mariotaku.twidere.model.RefreshTaskParam
|
||||||
import org.mariotaku.twidere.model.TwitterListResponse
|
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.event.GetActivitiesTaskEvent
|
import org.mariotaku.twidere.model.event.GetActivitiesTaskEvent
|
||||||
|
import org.mariotaku.twidere.model.task.GetTimelineResult
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
|
||||||
import org.mariotaku.twidere.task.BaseAbstractTask
|
import org.mariotaku.twidere.task.BaseAbstractTask
|
||||||
import org.mariotaku.twidere.util.*
|
import org.mariotaku.twidere.util.*
|
||||||
|
@ -39,26 +34,21 @@ import java.util.*
|
||||||
*/
|
*/
|
||||||
abstract class GetActivitiesTask(
|
abstract class GetActivitiesTask(
|
||||||
context: Context
|
context: Context
|
||||||
) : BaseAbstractTask<RefreshTaskParam, List<TwitterListResponse<Activity>>, (Boolean) -> Unit>(context) {
|
) : BaseAbstractTask<RefreshTaskParam, List<GetTimelineResult?>, (Boolean) -> Unit>(context) {
|
||||||
|
|
||||||
private val profileImageSize = context.getString(R.string.profile_image_size)
|
|
||||||
|
|
||||||
protected abstract val errorInfoKey: String
|
protected abstract val errorInfoKey: String
|
||||||
|
|
||||||
protected abstract val contentUri: Uri
|
protected abstract val contentUri: Uri
|
||||||
|
|
||||||
override fun doLongOperation(param: RefreshTaskParam): List<TwitterListResponse<Activity>> {
|
override fun doLongOperation(param: RefreshTaskParam): List<GetTimelineResult?> {
|
||||||
if (param.shouldAbort) return emptyList()
|
if (param.shouldAbort) return emptyList()
|
||||||
val accountKeys = param.accountKeys
|
val accountKeys = param.accountKeys
|
||||||
val cr = context.contentResolver
|
|
||||||
val result = ArrayList<TwitterListResponse<Activity>>()
|
|
||||||
val loadItemLimit = preferences[loadItemLimitKey]
|
val loadItemLimit = preferences[loadItemLimitKey]
|
||||||
val saveReadPosition = BooleanArray(accountKeys.size)
|
val saveReadPosition = BooleanArray(accountKeys.size)
|
||||||
accountKeys.forEachIndexed { i, accountKey ->
|
val result = accountKeys.mapIndexed { i, accountKey ->
|
||||||
val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri, accountKey) <= 0
|
val noItemsBefore = DataStoreUtils.getActivitiesCount(context, contentUri, accountKey) <= 0
|
||||||
val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey,
|
val credentials = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey,
|
||||||
true) ?: return@forEachIndexed
|
true) ?: return@mapIndexed null
|
||||||
val microBlog = credentials.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
|
||||||
val paging = Paging()
|
val paging = Paging()
|
||||||
paging.count(loadItemLimit)
|
paging.count(loadItemLimit)
|
||||||
val maxId = param.getMaxId(i)
|
val maxId = param.getMaxId(i)
|
||||||
|
@ -76,9 +66,9 @@ abstract class GetActivitiesTask(
|
||||||
}
|
}
|
||||||
// We should delete old activities has intersection with new items
|
// We should delete old activities has intersection with new items
|
||||||
try {
|
try {
|
||||||
val activities = getActivities(microBlog, credentials, paging)
|
val activities = getActivities(credentials, paging)
|
||||||
val storeResult = storeActivities(cr, loadItemLimit, credentials, noItemsBefore,
|
val storeResult = storeActivities(credentials, activities, sinceId, maxId,
|
||||||
activities, sinceId, maxId, false)
|
loadItemLimit, noItemsBefore, false)
|
||||||
if (saveReadPosition[i]) {
|
if (saveReadPosition[i]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -93,17 +83,19 @@ abstract class GetActivitiesTask(
|
||||||
} else if (e.isCausedByNetworkIssue) {
|
} else if (e.isCausedByNetworkIssue) {
|
||||||
errorInfoStore[errorInfoKey, accountKey] = ErrorInfoStore.CODE_NETWORK_ERROR
|
errorInfoStore[errorInfoKey, accountKey] = ErrorInfoStore.CODE_NETWORK_ERROR
|
||||||
}
|
}
|
||||||
|
return@mapIndexed GetTimelineResult(e)
|
||||||
} catch (e: GetStatusesTask.GetTimelineException) {
|
} catch (e: GetStatusesTask.GetTimelineException) {
|
||||||
result.add(TwitterListResponse(accountKey, e))
|
return@mapIndexed GetTimelineResult(e)
|
||||||
}
|
}
|
||||||
|
return@mapIndexed GetTimelineResult(null)
|
||||||
}
|
}
|
||||||
setLocalReadPosition(accountKeys, saveReadPosition)
|
setLocalReadPosition(accountKeys, saveReadPosition)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterExecute(handler: ((Boolean) -> Unit)?, result: List<TwitterListResponse<Activity>>) {
|
override fun afterExecute(handler: ((Boolean) -> Unit)?, result: List<GetTimelineResult?>) {
|
||||||
context.contentResolver.notifyChange(contentUri, null)
|
context.contentResolver.notifyChange(contentUri, null)
|
||||||
val exception = AsyncTwitterWrapper.getException(result)
|
val exception = result.firstOrNull { it?.exception != null }?.exception
|
||||||
bus.post(GetActivitiesTaskEvent(contentUri, false, exception))
|
bus.post(GetActivitiesTaskEvent(contentUri, false, exception))
|
||||||
handler?.invoke(true)
|
handler?.invoke(true)
|
||||||
}
|
}
|
||||||
|
@ -114,26 +106,24 @@ abstract class GetActivitiesTask(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
protected abstract fun getActivities(twitter: MicroBlog, details: AccountDetails, paging: Paging): ResponseList<Activity>
|
protected abstract fun getActivities(account: AccountDetails, paging: Paging): List<ParcelableActivity>
|
||||||
|
|
||||||
protected abstract fun setLocalReadPosition(accountKeys: Array<UserKey>, saveReadPosition: BooleanArray)
|
protected abstract fun setLocalReadPosition(accountKeys: Array<UserKey>, saveReadPosition: BooleanArray)
|
||||||
|
|
||||||
private fun storeActivities(cr: ContentResolver, loadItemLimit: Int, details: AccountDetails,
|
private fun storeActivities(details: AccountDetails, activities: List<ParcelableActivity>,
|
||||||
noItemsBefore: Boolean, activities: ResponseList<Activity>,
|
sinceId: String?, maxId: String?, loadItemLimit: Int, noItemsBefore: Boolean,
|
||||||
sinceId: String?, maxId: String?, notify: Boolean): Int {
|
notify: Boolean): Int {
|
||||||
|
val cr = context.contentResolver
|
||||||
val deleteBound = LongArray(2) { -1 }
|
val deleteBound = LongArray(2) { -1 }
|
||||||
val valuesList = ArrayList<ContentValues>()
|
val valuesList = ArrayList<ContentValues>()
|
||||||
var minIdx = -1
|
var minIdx = -1
|
||||||
var minPositionKey: Long = -1
|
var minPositionKey: Long = -1
|
||||||
if (!activities.isEmpty()) {
|
if (!activities.isEmpty()) {
|
||||||
val firstSortId = activities.first().createdAt.time
|
val firstSortId = activities.first().timestamp
|
||||||
val lastSortId = activities.last().createdAt.time
|
val lastSortId = activities.last().timestamp
|
||||||
// Get id diff of first and last item
|
// Get id diff of first and last item
|
||||||
val sortDiff = firstSortId - lastSortId
|
val sortDiff = firstSortId - lastSortId
|
||||||
for (i in activities.indices) {
|
activities.forEachIndexed { i, activity ->
|
||||||
val item = activities[i]
|
|
||||||
val activity = ParcelableActivityUtils.fromActivity(item, details.key, details.type,
|
|
||||||
false, profileImageSize)
|
|
||||||
mediaPreloader.preloadActivity(activity)
|
mediaPreloader.preloadActivity(activity)
|
||||||
activity.position_key = GetStatusesTask.getPositionKey(activity.timestamp,
|
activity.position_key = GetStatusesTask.getPositionKey(activity.timestamp,
|
||||||
activity.timestamp, lastSortId, sortDiff, i, activities.size)
|
activity.timestamp, lastSortId, sortDiff, i, activities.size)
|
||||||
|
@ -147,7 +137,7 @@ abstract class GetActivitiesTask(
|
||||||
} else {
|
} else {
|
||||||
deleteBound[1] = Math.max(deleteBound[1], activity.max_sort_position)
|
deleteBound[1] = Math.max(deleteBound[1], activity.max_sort_position)
|
||||||
}
|
}
|
||||||
if (minIdx == -1 || item < activities[minIdx]) {
|
if (minIdx == -1 || activity < activities[minIdx]) {
|
||||||
minIdx = i
|
minIdx = i
|
||||||
minPositionKey = activity.position_key
|
minPositionKey = activity.position_key
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
import org.mariotaku.twidere.model.RefreshTaskParam
|
import org.mariotaku.twidere.model.RefreshTaskParam
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.event.GetStatusesTaskEvent
|
import org.mariotaku.twidere.model.event.GetStatusesTaskEvent
|
||||||
|
import org.mariotaku.twidere.model.task.GetTimelineResult
|
||||||
import org.mariotaku.twidere.model.util.AccountUtils
|
import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns
|
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns
|
||||||
|
@ -41,13 +42,13 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||||
*/
|
*/
|
||||||
abstract class GetStatusesTask(
|
abstract class GetStatusesTask(
|
||||||
context: Context
|
context: Context
|
||||||
) : BaseAbstractTask<RefreshTaskParam, List<GetStatusesTask.GetStatusesResult?>, (Boolean) -> Unit>(context) {
|
) : BaseAbstractTask<RefreshTaskParam, List<GetTimelineResult?>, (Boolean) -> Unit>(context) {
|
||||||
|
|
||||||
protected abstract val contentUri: Uri
|
protected abstract val contentUri: Uri
|
||||||
|
|
||||||
protected abstract val errorInfoKey: String
|
protected abstract val errorInfoKey: String
|
||||||
|
|
||||||
override fun doLongOperation(param: RefreshTaskParam): List<GetStatusesResult?> {
|
override fun doLongOperation(param: RefreshTaskParam): List<GetTimelineResult?> {
|
||||||
if (param.shouldAbort) return emptyList()
|
if (param.shouldAbort) return emptyList()
|
||||||
val accountKeys = param.accountKeys
|
val accountKeys = param.accountKeys
|
||||||
val loadItemLimit = preferences[loadItemLimitKey]
|
val loadItemLimit = preferences[loadItemLimitKey]
|
||||||
|
@ -90,7 +91,7 @@ abstract class GetStatusesTask(
|
||||||
if (storeResult != 0) {
|
if (storeResult != 0) {
|
||||||
throw GetTimelineException(storeResult)
|
throw GetTimelineException(storeResult)
|
||||||
}
|
}
|
||||||
return@mapIndexed GetStatusesResult(null)
|
return@mapIndexed GetTimelineResult(null)
|
||||||
} catch (e: MicroBlogException) {
|
} catch (e: MicroBlogException) {
|
||||||
DebugLog.w(LOGTAG, tr = e)
|
DebugLog.w(LOGTAG, tr = e)
|
||||||
if (e.isCausedByNetworkIssue) {
|
if (e.isCausedByNetworkIssue) {
|
||||||
|
@ -98,14 +99,14 @@ abstract class GetStatusesTask(
|
||||||
} else if (e.statusCode == 401) {
|
} else if (e.statusCode == 401) {
|
||||||
// Unauthorized
|
// Unauthorized
|
||||||
}
|
}
|
||||||
return@mapIndexed GetStatusesResult(e)
|
return@mapIndexed GetTimelineResult(e)
|
||||||
} catch (e: GetTimelineException) {
|
} catch (e: GetTimelineException) {
|
||||||
return@mapIndexed GetStatusesResult(e)
|
return@mapIndexed GetTimelineResult(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterExecute(handler: ((Boolean) -> Unit)?, result: List<GetStatusesResult?>) {
|
override fun afterExecute(handler: ((Boolean) -> Unit)?, result: List<GetTimelineResult?>) {
|
||||||
context.contentResolver.notifyChange(contentUri, null)
|
context.contentResolver.notifyChange(contentUri, null)
|
||||||
val exception = result.firstOrNull { it?.exception != null }?.exception
|
val exception = result.firstOrNull { it?.exception != null }?.exception
|
||||||
bus.post(GetStatusesTaskEvent(contentUri, false, exception))
|
bus.post(GetStatusesTaskEvent(contentUri, false, exception))
|
||||||
|
@ -141,8 +142,7 @@ abstract class GetStatusesTask(
|
||||||
val sortDiff = firstSortId - lastSortId
|
val sortDiff = firstSortId - lastSortId
|
||||||
|
|
||||||
val creator = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java)
|
val creator = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java)
|
||||||
for (i in 0 until statuses.size) {
|
statuses.forEachIndexed { i, status ->
|
||||||
val status = statuses[i]
|
|
||||||
ParcelableStatusUtils.updateExtraInformation(status, account)
|
ParcelableStatusUtils.updateExtraInformation(status, account)
|
||||||
status.position_key = getPositionKey(status.timestamp, status.sort_id, lastSortId,
|
status.position_key = getPositionKey(status.timestamp, status.sort_id, lastSortId,
|
||||||
sortDiff, i, statuses.size)
|
sortDiff, i, statuses.size)
|
||||||
|
@ -210,8 +210,6 @@ abstract class GetStatusesTask(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class GetStatusesResult(val exception: Exception?)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val ERROR_LOAD_GAP = 1
|
const val ERROR_LOAD_GAP = 1
|
||||||
|
|
Loading…
Reference in New Issue