1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-01-20 20:18:35 +01:00

migrating to kotlin

This commit is contained in:
Mariotaku Lee 2016-07-02 12:37:42 +08:00
parent c6bc1041e2
commit 3f744f9e50
29 changed files with 1278 additions and 1441 deletions

View File

@ -145,7 +145,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
val loader = ConversationLoader(activity, status!!, sinceId,
maxId, sinceSortId, maxSortId, adapter!!.getData(), true, loadingMore)
// Setting comparator to null lets statuses sort ascending
loader.setComparator(null)
loader.comparator = null
return loader
}
@ -294,7 +294,7 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
override fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, statusPosition: Int) {
val status = adapter!!.getStatus(statusPosition)
if (status == null || media == null) return
if (status == null) return
IntentUtils.openMedia(activity, status, media, null,
preferences.getBoolean(SharedPreferenceConstants.KEY_NEW_DOCUMENT_API))

View File

@ -1,162 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import org.mariotaku.commons.parcel.ParcelUtils;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.SearchQuery;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
import org.mariotaku.twidere.util.Nullables;
import org.mariotaku.twidere.util.Utils;
import java.util.ArrayList;
import java.util.List;
public class ConversationLoader extends MicroBlogAPIStatusesLoader {
@NonNull
private final ParcelableStatus mStatus;
private final long mSinceSortId, mMaxSortId;
private boolean mCanLoadAllReplies;
public ConversationLoader(final Context context, @NonNull final ParcelableStatus status,
final String sinceId, final String maxId,
final long sinceSortId, final long maxSortId,
final List<ParcelableStatus> data, final boolean fromUser,
final boolean loadingMore) {
super(context, status.account_key, sinceId, maxId, -1, data, null, -1, fromUser, loadingMore);
mStatus = Nullables.assertNonNull(ParcelUtils.clone(status));
mSinceSortId = sinceSortId;
mMaxSortId = maxSortId;
ParcelableStatusUtils.makeOriginalStatus(mStatus);
}
@NonNull
@Override
public List<Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull final ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
mCanLoadAllReplies = false;
final ParcelableStatus status = mStatus;
switch (ParcelableAccountUtils.getAccountType(credentials)) {
case ParcelableAccount.Type.TWITTER: {
final boolean isOfficial = Utils.isOfficialCredentials(getContext(), credentials);
mCanLoadAllReplies = isOfficial;
if (isOfficial) {
return microBlog.showConversation(status.id, paging);
} else {
return showConversationCompat(microBlog, credentials, status, true);
}
}
case ParcelableAccount.Type.STATUSNET: {
mCanLoadAllReplies = true;
if (status.extras != null && status.extras.statusnet_conversation_id != null) {
return microBlog.getStatusNetConversation(status.extras.statusnet_conversation_id,
paging);
}
return microBlog.showConversation(status.id, paging);
}
case ParcelableAccount.Type.FANFOU: {
mCanLoadAllReplies = true;
return microBlog.getContextTimeline(status.id, paging);
}
}
// Set to true because there's no conversation support on this platform
mCanLoadAllReplies = true;
return showConversationCompat(microBlog, credentials, status, false);
}
protected List<Status> showConversationCompat(@NonNull final MicroBlog twitter,
@NonNull final ParcelableCredentials credentials,
@NonNull final ParcelableStatus status,
final boolean loadReplies) throws MicroBlogException {
final List<Status> statuses = new ArrayList<>();
final String maxId = getMaxId(), sinceId = getSinceId();
final long maxSortId = getMaxSortId(), sinceSortId = getSinceSortId();
final boolean noSinceMaxId = maxId == null && sinceId == null;
// Load conversations
if ((maxId != null && maxSortId < status.sort_id) || noSinceMaxId) {
String inReplyToId = maxId != null ? maxId : status.in_reply_to_status_id;
int count = 0;
while (inReplyToId != null && count < 10) {
final Status item = twitter.showStatus(inReplyToId);
inReplyToId = item.getInReplyToStatusId();
statuses.add(item);
count++;
}
}
if (loadReplies) {
// Load replies
if ((sinceId != null && sinceSortId > status.sort_id) || noSinceMaxId) {
SearchQuery query = new SearchQuery();
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
query.query("to:" + status.user_screen_name);
} else {
query.query("@" + status.user_screen_name);
}
query.sinceId(sinceId != null ? sinceId : status.id);
try {
for (Status item : twitter.search(query)) {
if (TextUtils.equals(item.getInReplyToStatusId(), status.id)) {
statuses.add(item);
}
}
} catch (MicroBlogException e) {
// Ignore for now
}
}
}
return statuses;
}
public boolean canLoadAllReplies() {
return mCanLoadAllReplies;
}
public long getSinceSortId() {
return mSinceSortId;
}
public long getMaxSortId() {
return mMaxSortId;
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(SQLiteDatabase database, ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, false);
}
}

View File

@ -0,0 +1,148 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import android.text.TextUtils
import org.mariotaku.commons.parcel.ParcelUtils
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.SearchQuery
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableAccount
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.util.ParcelableAccountUtils
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
import org.mariotaku.twidere.util.InternalTwitterContentUtils
import org.mariotaku.twidere.util.MicroBlogAPIFactory
import org.mariotaku.twidere.util.Nullables
import org.mariotaku.twidere.util.Utils
import java.util.*
class ConversationLoader(
context: Context,
status: ParcelableStatus,
sinceId: String?,
maxId: String?,
val sinceSortId: Long,
val maxSortId: Long,
adapterData: List<ParcelableStatus>?,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, status.account_key, sinceId, maxId, -1, adapterData, null, -1,
fromUser, loadingMore) {
private val status: ParcelableStatus
private var canLoadAllReplies: Boolean = false
init {
this.status = Nullables.assertNonNull(ParcelUtils.clone(status))
ParcelableStatusUtils.makeOriginalStatus(this.status)
}
@Throws(MicroBlogException::class)
public override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): List<Status> {
canLoadAllReplies = false
when (ParcelableAccountUtils.getAccountType(credentials)) {
ParcelableAccount.Type.TWITTER -> {
val isOfficial = Utils.isOfficialCredentials(context, credentials)
canLoadAllReplies = isOfficial
if (isOfficial) {
return microBlog.showConversation(status.id, paging)
} else {
return showConversationCompat(microBlog, credentials, status, true)
}
}
ParcelableAccount.Type.STATUSNET -> {
canLoadAllReplies = true
if (status.extras != null && status.extras.statusnet_conversation_id != null) {
return microBlog.getStatusNetConversation(status.extras.statusnet_conversation_id, paging)
}
return microBlog.showConversation(status.id, paging)
}
ParcelableAccount.Type.FANFOU -> {
canLoadAllReplies = true
return microBlog.getContextTimeline(status.id, paging)
}
}
// Set to true because there's no conversation support on this platform
canLoadAllReplies = true
return showConversationCompat(microBlog, credentials, status, false)
}
@Throws(MicroBlogException::class)
protected fun showConversationCompat(twitter: MicroBlog,
credentials: ParcelableCredentials,
status: ParcelableStatus,
loadReplies: Boolean): List<Status> {
val statuses = ArrayList<Status>()
val noSinceMaxId = maxId == null && sinceId == null
// Load conversations
if (maxId != null && maxSortId < status.sort_id || noSinceMaxId) {
var inReplyToId: String? = maxId ?: status.in_reply_to_status_id
var count = 0
while (inReplyToId != null && count < 10) {
val item = twitter.showStatus(inReplyToId)
inReplyToId = item.inReplyToStatusId
statuses.add(item)
count++
}
}
if (loadReplies) {
// Load replies
if (sinceId != null && sinceSortId > status.sort_id || noSinceMaxId) {
val query = SearchQuery()
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
query.query("to:${status.user_screen_name}")
} else {
query.query("@${status.user_screen_name}")
}
query.sinceId(sinceId ?: status.id)
try {
for (item in twitter.search(query)) {
if (TextUtils.equals(item.inReplyToStatusId, status.id)) {
statuses.add(item)
}
}
} catch (e: MicroBlogException) {
// Ignore for now
}
}
}
return statuses
}
fun canLoadAllReplies(): Boolean {
return canLoadAllReplies
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, false)
}
}

View File

@ -1,46 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.List;
public final class DummyParcelableStatusesLoader extends ParcelableStatusesLoader {
public DummyParcelableStatusesLoader(final Context context) {
this(context, null, false);
}
public DummyParcelableStatusesLoader(final Context context, final List<ParcelableStatus> data, boolean fromUser) {
super(context, data, -1, fromUser);
}
@Override
public ListResponse<ParcelableStatus> loadInBackground() {
final List<ParcelableStatus> data = getData();
if (data != null) return ListResponse.getListInstance(data);
return ListResponse.emptyListInstance();
}
}

View File

@ -0,0 +1,33 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import org.mariotaku.twidere.model.ListResponse
import org.mariotaku.twidere.model.ParcelableStatus
class DummyParcelableStatusesLoader @JvmOverloads constructor(context: Context, data: List<ParcelableStatus>? = null, fromUser: Boolean = false) : ParcelableStatusesLoader(context, data, -1, fromUser) {
override fun loadInBackground(): ListResponse<ParcelableStatus> {
return ListResponse.getListInstance(data)
}
}

View File

@ -1,71 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class GroupTimelineLoader extends MicroBlogAPIStatusesLoader {
private final String mGroupId;
private final String mGroupName;
public GroupTimelineLoader(final Context context, final UserKey accountKey, final String groupId,
final String groupName, final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mGroupId = groupId;
mGroupName = groupName;
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull final ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
if (mGroupId != null)
return microBlog.getGroupStatuses(mGroupId, paging);
else if (mGroupName != null)
return microBlog.getGroupStatusesByName(mGroupName, paging);
throw new MicroBlogException("No group name or id given");
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
}

View File

@ -0,0 +1,73 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class GroupTimelineLoader(
context: Context,
accountKey: UserKey?,
private val groupId: String?,
private val groupName: String?,
sinceId: String?,
maxId: String?,
adapterData: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): ResponseList<Status> {
when {
groupId != null -> {
return microBlog.getGroupStatuses(groupId, paging)
}
groupName != null -> {
return microBlog.getGroupStatusesByName(groupName, paging)
}
else -> {
throw MicroBlogException("No group name or id given")
}
}
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, true)
}
}

View File

@ -1,56 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.os.Bundle;
import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.ParcelableStatus;
import java.util.Collections;
import java.util.List;
import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_STATUSES;
public class IntentExtrasStatusesLoader extends ParcelableStatusesLoader {
private final Bundle mExtras;
public IntentExtrasStatusesLoader(final Context context, final Bundle extras,
final List<ParcelableStatus> data, final boolean fromUser) {
super(context, data, -1, fromUser);
mExtras = extras;
}
@Override
public ListResponse<ParcelableStatus> loadInBackground() {
final List<ParcelableStatus> data = getData();
if (mExtras != null && mExtras.containsKey(EXTRA_STATUSES)) {
final List<ParcelableStatus> users = mExtras.getParcelableArrayList(EXTRA_STATUSES);
if (data != null && users != null) {
data.addAll(users);
Collections.sort(data);
}
}
return ListResponse.getListInstance(data);
}
}

View File

@ -0,0 +1,43 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.os.Bundle
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_STATUSES
import org.mariotaku.twidere.model.ListResponse
import org.mariotaku.twidere.model.ParcelableStatus
import java.util.*
class IntentExtrasStatusesLoader(context: Context, private val mExtras: Bundle?,
data: List<ParcelableStatus>, fromUser: Boolean) : ParcelableStatusesLoader(context, data, -1, fromUser) {
override fun loadInBackground(): ListResponse<ParcelableStatus> {
if (mExtras != null && mExtras.containsKey(EXTRA_STATUSES)) {
val users = mExtras.getParcelableArrayList<ParcelableStatus>(EXTRA_STATUSES)
if (users != null) {
data.addAll(users)
Collections.sort(data)
}
}
return ListResponse.getListInstance(data)
}
}

View File

@ -1,149 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import org.apache.commons.lang3.StringUtils;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.SearchQuery;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.microblog.library.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.Utils;
import java.util.List;
public class MediaTimelineLoader extends MicroBlogAPIStatusesLoader {
@Nullable
private final UserKey mUserKey;
@Nullable
private final String mUserScreenName;
private User mUser;
public MediaTimelineLoader(final Context context, final UserKey accountKey, @Nullable final UserKey userKey,
@Nullable final String screenName, final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
mUserKey = userKey;
mUserScreenName = screenName;
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull final ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
final Context context = getContext();
switch (ParcelableAccountUtils.getAccountType(credentials)) {
case ParcelableAccount.Type.TWITTER: {
if (Utils.isOfficialCredentials(context, credentials)) {
if (mUserKey != null) {
return microBlog.getMediaTimeline(mUserKey.getId(), paging);
}
if (mUserScreenName != null) {
return microBlog.getMediaTimelineByScreenName(mUserScreenName, paging);
}
} else {
final String screenName;
if (mUserScreenName != null) {
screenName = mUserScreenName;
} else if (mUserKey != null) {
if (mUser == null) {
mUser = TwitterWrapper.tryShowUser(microBlog, mUserKey.getId(), null,
credentials.account_type);
}
screenName = mUser.getScreenName();
} else {
throw new MicroBlogException("Invalid parameters");
}
final SearchQuery query;
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
query = new SearchQuery("from:" + screenName + " filter:media exclude:retweets");
} else {
query = new SearchQuery("@" + screenName + " pic.twitter.com -RT");
}
query.paging(paging);
final ResponseList<Status> result = new ResponseList<>();
for (Status status : microBlog.search(query)) {
final User user = status.getUser();
if ((mUserKey != null && TextUtils.equals(user.getId(), mUserKey.getId())) ||
StringUtils.endsWithIgnoreCase(user.getScreenName(), mUserScreenName)) {
result.add(status);
}
}
return result;
}
throw new MicroBlogException("Wrong user");
}
case ParcelableAccount.Type.FANFOU: {
if (mUserKey != null) {
return microBlog.getPhotosUserTimeline(mUserKey.getId(), paging);
}
if (mUserScreenName != null) {
return microBlog.getPhotosUserTimeline(mUserScreenName, paging);
}
throw new MicroBlogException("Wrong user");
}
}
throw new MicroBlogException("Not implemented");
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
final UserKey retweetUserId = status.is_retweet ? status.user_key : null;
return !isMyTimeline() && InternalTwitterContentUtils.isFiltered(database, retweetUserId,
status.text_plain, status.quoted_text_plain, status.spans, status.quoted_spans,
status.source, status.quoted_source, null, status.quoted_user_key);
}
private boolean isMyTimeline() {
final UserKey accountKey = getAccountKey();
if (accountKey == null) return false;
if (mUserKey != null) {
return mUserKey.maybeEquals(accountKey);
} else {
final String accountScreenName = DataStoreUtils.getAccountScreenName(getContext(), accountKey);
return accountScreenName != null && accountScreenName.equalsIgnoreCase(mUserScreenName);
}
}
}

View File

@ -0,0 +1,131 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import android.text.TextUtils
import org.apache.commons.lang3.StringUtils
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.*
import org.mariotaku.twidere.model.ParcelableAccount
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableAccountUtils
import org.mariotaku.twidere.util.*
class MediaTimelineLoader(
context: Context,
accountKey: UserKey,
private val userKey: UserKey?,
private val screenName: String?,
sinceId: String?,
maxId: String?,
data: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
private var user: User? = null
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): ResponseList<Status> {
val context = context
when (ParcelableAccountUtils.getAccountType(credentials)) {
ParcelableAccount.Type.TWITTER -> {
if (Utils.isOfficialCredentials(context, credentials)) {
if (userKey != null) {
return microBlog.getMediaTimeline(userKey.id, paging)
}
if (screenName != null) {
return microBlog.getMediaTimelineByScreenName(screenName, paging)
}
} else {
val screenName: String
if (this.screenName != null) {
screenName = this.screenName
} else if (userKey != null) {
if (user == null) {
user = TwitterWrapper.tryShowUser(microBlog, userKey.id, null,
credentials.account_type)
}
screenName = user!!.screenName
} else {
throw MicroBlogException("Invalid parameters")
}
val query: SearchQuery
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
query = SearchQuery("from:$screenName filter:media exclude:retweets")
} else {
query = SearchQuery("@$screenName pic.twitter.com -RT")
}
query.paging(paging)
val result = ResponseList<Status>()
for (status in microBlog.search(query)) {
val user = status.user
if (userKey != null && TextUtils.equals(user.id, userKey.id) || StringUtils.endsWithIgnoreCase(user.screenName, this.screenName)) {
result.add(status)
}
}
return result
}
throw MicroBlogException("Wrong user")
}
ParcelableAccount.Type.FANFOU -> {
if (userKey != null) {
return microBlog.getPhotosUserTimeline(userKey.id, paging)
}
if (screenName != null) {
return microBlog.getPhotosUserTimeline(screenName, paging)
}
throw MicroBlogException("Wrong user")
}
}
throw MicroBlogException("Not implemented")
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
val retweetUserId = if (status.is_retweet) status.user_key else null
return !isMyTimeline && InternalTwitterContentUtils.isFiltered(database, retweetUserId,
status.text_plain, status.quoted_text_plain, status.spans, status.quoted_spans,
status.source, status.quoted_source, null, status.quoted_user_key)
}
private val isMyTimeline: Boolean
get() {
val accountKey = accountKey ?: return false
if (userKey != null) {
return userKey.maybeEquals(accountKey)
} else {
val accountScreenName = DataStoreUtils.getAccountScreenName(context, accountKey)
return accountScreenName != null && accountScreenName.equals(screenName!!, ignoreCase = true)
}
}
}

View File

@ -1,309 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.util.Log;
import com.nostra13.universalimageloader.cache.disc.DiskCache;
import com.nostra13.universalimageloader.utils.IoUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.commons.logansquare.LoganSquareMapperFinder;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.File;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
public abstract class MicroBlogAPIStatusesLoader extends ParcelableStatusesLoader {
@Nullable
private final UserKey mAccountKey;
private final String mMaxId, mSinceId;
private final int mPage;
@Nullable
private final Object[] mSavedStatusesFileArgs;
private final boolean mLoadingMore;
// Statuses sorted descending by default
private Comparator<ParcelableStatus> mComparator = ParcelableStatus.REVERSE_COMPARATOR;
private AtomicReference<MicroBlogException> mException = new AtomicReference<>();
@Inject
protected DiskCache mFileCache;
@Inject
protected SharedPreferencesWrapper mPreferences;
@Inject
protected UserColorNameManager mUserColorNameManager;
public MicroBlogAPIStatusesLoader(@NonNull final Context context,
@Nullable final UserKey accountKey,
final String sinceId, final String maxId,
int page, @Nullable final List<ParcelableStatus> data,
@Nullable final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser, boolean loadingMore) {
super(context, data, tabPosition, fromUser);
GeneralComponentHelper.build(context).inject(this);
mAccountKey = accountKey;
mMaxId = maxId;
mSinceId = sinceId;
mPage = page;
mSavedStatusesFileArgs = savedStatusesArgs;
mLoadingMore = loadingMore;
}
@SuppressWarnings("unchecked")
@Override
public final ListResponse<ParcelableStatus> loadInBackground() {
final Context context = getContext();
if (mAccountKey == null) {
return ListResponse.getListInstance(new MicroBlogException("No Account"));
}
final ParcelableCredentials credentials = ParcelableCredentialsUtils.getCredentials(context,
mAccountKey);
if (credentials == null) {
return ListResponse.getListInstance(new MicroBlogException("No Account"));
}
List<ParcelableStatus> data = getData();
if (data == null) {
data = new CopyOnWriteArrayList<>();
}
if (isFirstLoad() && getTabPosition() >= 0) {
final List<ParcelableStatus> cached = getCachedData();
if (cached != null) {
data.addAll(cached);
if (mComparator != null) {
Collections.sort(data, mComparator);
} else {
Collections.sort(data);
}
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data));
}
}
if (!isFromUser()) return ListResponse.getListInstance(data);
final MicroBlog twitter = MicroBlogAPIFactory.getInstance(context, credentials, true,
true);
if (twitter == null) {
return ListResponse.getListInstance(new MicroBlogException("No Account"));
}
final List<? extends Status> statuses;
final boolean noItemsBefore = data.isEmpty();
final int loadItemLimit = mPreferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
try {
final Paging paging = new Paging();
processPaging(credentials, loadItemLimit, paging);
statuses = getStatuses(twitter, credentials, paging);
} catch (final MicroBlogException e) {
// mHandler.post(new ShowErrorRunnable(e));
mException.set(e);
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
}
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data), e);
}
final String[] statusIds = new String[statuses.size()];
int minIdx = -1;
int rowsDeleted = 0;
for (int i = 0, j = statuses.size(); i < j; i++) {
final Status status = statuses.get(i);
if (minIdx == -1 || status.compareTo(statuses.get(minIdx)) < 0) {
minIdx = i;
}
statusIds[i] = status.getId();
if (deleteStatus(data, status.getId())) {
rowsDeleted++;
}
}
// Insert a gap.
final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, mMaxId);
final boolean noRowsDeleted = rowsDeleted == 0;
final boolean insertGap = minIdx != -1 && (noRowsDeleted || deletedOldGap) && !noItemsBefore
&& statuses.size() >= loadItemLimit && !mLoadingMore;
for (int i = 0, j = statuses.size(); i < j; i++) {
final Status status = statuses.get(i);
final ParcelableStatus item = ParcelableStatusUtils.fromStatus(status, mAccountKey,
insertGap && isGapEnabled() && minIdx == i);
ParcelableStatusUtils.updateExtraInformation(item, credentials, mUserColorNameManager);
data.add(item);
}
final SQLiteDatabase db = TwidereApplication.Companion.getInstance(context).getSqLiteDatabase();
final ParcelableStatus[] array = data.toArray(new ParcelableStatus[data.size()]);
for (int i = 0, size = array.length; i < size; i++) {
final ParcelableStatus status = array[i];
final boolean filtered = shouldFilterStatus(db, status);
if (filtered) {
if (!status.is_gap && i != size - 1) {
data.remove(status);
} else {
status.is_filtered = true;
}
}
}
if (mComparator != null) {
Collections.sort(data, mComparator);
} else {
Collections.sort(data);
}
saveCachedData(data);
return ListResponse.getListInstance(new CopyOnWriteArrayList<>(data));
}
public final void setComparator(Comparator<ParcelableStatus> comparator) {
mComparator = comparator;
}
public String getSinceId() {
return mSinceId;
}
public String getMaxId() {
return mMaxId;
}
public int getPage() {
return mPage;
}
@Nullable
public UserKey getAccountKey() {
return mAccountKey;
}
@NonNull
protected abstract List<? extends Status> getStatuses(@NonNull MicroBlog microBlog,
@NonNull ParcelableCredentials credentials,
@NonNull Paging paging) throws MicroBlogException;
@WorkerThread
protected abstract boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status);
@Nullable
public MicroBlogException getException() {
return mException.get();
}
@Override
protected void onStartLoading() {
mException.set(null);
super.onStartLoading();
}
protected void processPaging(@NonNull ParcelableCredentials credentials, int loadItemLimit, @NonNull final Paging paging) {
paging.setCount(loadItemLimit);
if (mMaxId != null) {
paging.setMaxId(mMaxId);
}
if (mSinceId != null) {
paging.setSinceId(mSinceId);
if (mMaxId == null) {
paging.setLatestResults(true);
}
}
}
protected boolean isGapEnabled() {
return true;
}
private List<ParcelableStatus> getCachedData() {
final String key = getSerializationKey();
if (key == null) return null;
final File file = mFileCache.get(key);
if (file == null) return null;
return JsonSerializer.parseList(file, ParcelableStatus.class);
}
private String getSerializationKey() {
if (mSavedStatusesFileArgs == null) return null;
return TwidereArrayUtils.toString(mSavedStatusesFileArgs, '_', false);
}
private static final ExecutorService pool = Executors.newSingleThreadExecutor();
private void saveCachedData(final List<ParcelableStatus> data) {
final String key = getSerializationKey();
if (key == null || data == null) return;
final int databaseItemLimit = mPreferences.getInt(KEY_DATABASE_ITEM_LIMIT, DEFAULT_DATABASE_ITEM_LIMIT);
try {
final List<ParcelableStatus> statuses = data.subList(0, Math.min(databaseItemLimit, data.size()));
final PipedOutputStream pos = new PipedOutputStream();
final PipedInputStream pis = new PipedInputStream(pos);
final Future<Object> future = pool.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
LoganSquareMapperFinder.mapperFor(ParcelableStatus.class).serialize(statuses, pos);
return null;
}
});
final boolean saved = mFileCache.save(key, pis, new IoUtils.CopyListener() {
@Override
public boolean onBytesCopied(int current, int total) {
return !future.isDone();
}
});
if (BuildConfig.DEBUG) {
Log.v(LOGTAG, key + " saved: " + saved);
}
} catch (final Exception e) {
// Ignore
if (BuildConfig.DEBUG && !(e instanceof IOException)) {
Log.w(LOGTAG, e);
}
}
}
}

View File

@ -0,0 +1,262 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import android.util.Log
import com.nostra13.universalimageloader.cache.disc.DiskCache
import org.apache.commons.lang3.ArrayUtils
import org.mariotaku.commons.logansquare.LoganSquareMapperFinder
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.model.ListResponse
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import java.io.IOException
import java.io.PipedInputStream
import java.io.PipedOutputStream
import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicReference
import javax.inject.Inject
abstract class MicroBlogAPIStatusesLoader(
context: Context,
val accountKey: UserKey?,
val sinceId: String?,
val maxId: String?,
val page: Int,
adapterData: List<ParcelableStatus>?,
private val savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
private val loadingMore: Boolean
) : ParcelableStatusesLoader(context, adapterData, tabPosition, fromUser) {
// Statuses sorted descending by default
var comparator: Comparator<ParcelableStatus>? = ParcelableStatus.REVERSE_COMPARATOR
private val mException = AtomicReference<MicroBlogException>()
@Inject
lateinit var fileCache: DiskCache
@Inject
lateinit var preferences: SharedPreferencesWrapper
@Inject
lateinit var userColorNameManager: UserColorNameManager
init {
GeneralComponentHelper.build(context).inject(this)
}
@SuppressWarnings("unchecked")
override fun loadInBackground(): ListResponse<ParcelableStatus> {
val context = context
if (accountKey == null) {
return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account"))
}
val credentials = ParcelableCredentialsUtils.getCredentials(context,
accountKey) ?: return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account"))
var data: MutableList<ParcelableStatus>? = data
if (data == null) {
data = CopyOnWriteArrayList<ParcelableStatus>()
}
if (isFirstLoad && tabPosition >= 0) {
val cached = cachedData
if (cached != null) {
data.addAll(cached)
if (comparator != null) {
Collections.sort(data, comparator)
} else {
Collections.sort(data)
}
return ListResponse.getListInstance(CopyOnWriteArrayList(data))
}
}
if (!isFromUser) return ListResponse.getListInstance(data)
val twitter = MicroBlogAPIFactory.getInstance(context, credentials, true,
true) ?: return ListResponse.getListInstance<ParcelableStatus>(MicroBlogException("No Account"))
val statuses: List<Status>
val noItemsBefore = data.isEmpty()
val loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT)
try {
val paging = Paging()
processPaging(credentials, loadItemLimit, paging)
statuses = getStatuses(twitter, credentials, paging)
} catch (e: MicroBlogException) {
// mHandler.post(new ShowErrorRunnable(e));
mException.set(e)
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e)
}
return ListResponse.getListInstance(CopyOnWriteArrayList(data), e)
}
val statusIds = arrayOfNulls<String>(statuses.size)
var minIdx = -1
var rowsDeleted = 0
run {
var i = 0
val j = statuses.size
while (i < j) {
val status = statuses[i]
if (minIdx == -1 || status.compareTo(statuses[minIdx]) < 0) {
minIdx = i
}
statusIds[i] = status.id
if (deleteStatus(data, status.id)) {
rowsDeleted++
}
i++
}
}
// Insert a gap.
val deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, maxId)
val noRowsDeleted = rowsDeleted == 0
val insertGap = minIdx != -1 && (noRowsDeleted || deletedOldGap) && !noItemsBefore
&& statuses.size >= loadItemLimit && !loadingMore
run {
var i = 0
val j = statuses.size
while (i < j) {
val status = statuses[i]
val item = ParcelableStatusUtils.fromStatus(status, accountKey,
insertGap && isGapEnabled && minIdx == i)
ParcelableStatusUtils.updateExtraInformation(item, credentials, userColorNameManager)
data!!.add(item)
i++
}
}
val db = TwidereApplication.getInstance(context).sqLiteDatabase
val array = data.toTypedArray()
var i = 0
val size = array.size
while (i < size) {
val status = array[i]
val filtered = shouldFilterStatus(db, status)
if (filtered) {
if (!status.is_gap && i != size - 1) {
data.remove(status)
} else {
status.is_filtered = true
}
}
i++
}
if (comparator != null) {
Collections.sort(data, comparator)
} else {
Collections.sort(data)
}
saveCachedData(data)
return ListResponse.getListInstance(CopyOnWriteArrayList(data))
}
@Throws(MicroBlogException::class)
protected abstract fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): List<Status>
@WorkerThread
protected abstract fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean
val exception: MicroBlogException?
get() = mException.get()
override fun onStartLoading() {
mException.set(null)
super.onStartLoading()
}
protected open fun processPaging(credentials: ParcelableCredentials, loadItemLimit: Int, paging: Paging) {
paging.setCount(loadItemLimit)
if (maxId != null) {
paging.setMaxId(maxId)
}
if (sinceId != null) {
paging.setSinceId(sinceId)
if (maxId == null) {
paging.setLatestResults(true)
}
}
}
protected open val isGapEnabled: Boolean
get() = true
private val cachedData: List<ParcelableStatus>?
get() {
val key = serializationKey ?: return null
val file = fileCache.get(key) ?: return null
return JsonSerializer.parseList(file, ParcelableStatus::class.java)
}
private val serializationKey: String?
get() {
if (savedStatusesArgs == null) return null
return TwidereArrayUtils.toString(savedStatusesArgs, '_', false)
}
private fun saveCachedData(data: List<ParcelableStatus>?) {
val key = serializationKey
if (key == null || data == null) return
val databaseItemLimit = preferences.getInt(KEY_DATABASE_ITEM_LIMIT, DEFAULT_DATABASE_ITEM_LIMIT)
try {
val statuses = data.subList(0, Math.min(databaseItemLimit, data.size))
val pos = PipedOutputStream()
val pis = PipedInputStream(pos)
val future = pool.submit(Callable<kotlin.Any> {
LoganSquareMapperFinder.mapperFor(ParcelableStatus::class.java).serialize(statuses, pos)
null
})
val saved = fileCache.save(key, pis) { current, total -> !future.isDone }
if (BuildConfig.DEBUG) {
Log.v(LOGTAG, key + " saved: " + saved)
}
} catch (e: Exception) {
// Ignore
if (BuildConfig.DEBUG && e !is IOException) {
Log.w(LOGTAG, e)
}
}
}
companion object {
private val pool = Executors.newSingleThreadExecutor()
}
}

View File

@ -1,101 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.content.AsyncTaskLoader;
import android.text.TextUtils;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList;
import java.util.List;
public abstract class ParcelableStatusesLoader extends AsyncTaskLoader<List<ParcelableStatus>>
implements Constants, IExtendedLoader {
private final List<ParcelableStatus> mData = new NoDuplicatesArrayList<>();
private final boolean mFirstLoad;
private final int mTabPosition;
private boolean mFromUser;
public ParcelableStatusesLoader(final Context context, @Nullable final List<ParcelableStatus> data,
final int tabPosition, final boolean fromUser) {
super(context);
mFirstLoad = data == null;
if (data != null) {
mData.addAll(data);
}
mTabPosition = tabPosition;
mFromUser = fromUser;
}
@Override
public boolean isFromUser() {
return mFromUser;
}
@Override
public void setFromUser(boolean fromUser) {
mFromUser = fromUser;
}
protected boolean containsStatus(final String statusId) {
for (final ParcelableStatus status : mData) {
if (TextUtils.equals(status.id, statusId)) return true;
}
return false;
}
protected boolean deleteStatus(final List<ParcelableStatus> statuses, final String statusId) {
if (statuses == null || statuses.isEmpty()) return false;
boolean result = false;
for (int i = statuses.size() - 1; i >= 0; i--) {
if (TextUtils.equals(statuses.get(i).id, statusId)) {
statuses.remove(i);
result = true;
}
}
return result;
}
@Nullable
protected List<ParcelableStatus> getData() {
return mData;
}
protected int getTabPosition() {
return mTabPosition;
}
protected boolean isFirstLoad() {
return mFirstLoad;
}
@Override
protected void onStartLoading() {
forceLoad();
}
}

View File

@ -0,0 +1,79 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.support.v4.content.AsyncTaskLoader
import android.text.TextUtils
import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.loader.iface.IExtendedLoader
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList
abstract class ParcelableStatusesLoader(
context: Context,
adapterData: List<ParcelableStatus>?,
protected val tabPosition: Int,
private var fromUser: Boolean) : AsyncTaskLoader<List<ParcelableStatus>>(context), Constants, IExtendedLoader {
protected val data = NoDuplicatesArrayList<ParcelableStatus>()
protected val isFirstLoad: Boolean
init {
isFirstLoad = adapterData == null
if (adapterData != null) {
data.addAll(adapterData)
}
}
override fun isFromUser(): Boolean {
return fromUser
}
override fun setFromUser(fromUser: Boolean) {
this.fromUser = fromUser
}
protected fun containsStatus(statusId: String): Boolean {
for (status in this.data) {
if (TextUtils.equals(status.id, statusId)) return true
}
return false
}
protected fun deleteStatus(statuses: MutableList<ParcelableStatus>?, statusId: String): Boolean {
if (statuses == null || statuses.isEmpty()) return false
var result = false
for (i in statuses.indices.reversed()) {
if (TextUtils.equals(statuses[i].id, statusId)) {
statuses.removeAt(i)
result = true
}
}
return result
}
override fun onStartLoading() {
forceLoad()
}
}

View File

@ -1,61 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class PublicTimelineLoader extends MicroBlogAPIStatusesLoader {
public PublicTimelineLoader(final Context context, final UserKey accountId,
final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountId, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull final ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
return microBlog.getPublicTimeline(paging);
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
}

View File

@ -0,0 +1,60 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class PublicTimelineLoader(
context: Context,
accountId: UserKey?,
sinceId: String?,
maxId: String?,
adapterData: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountId, sinceId, maxId, -1, adapterData, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): ResponseList<Status> {
return microBlog.getPublicTimeline(paging)
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, true)
}
}

View File

@ -1,63 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class RetweetsOfMeLoader extends MicroBlogAPIStatusesLoader {
public RetweetsOfMeLoader(final Context context, final UserKey accountKey,
final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws MicroBlogException {
return microBlog.getRetweetsOfMe(paging);
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, null, status.text_plain,
status.quoted_text_plain, status.spans, status.quoted_spans, status.source,
status.quoted_source, status.retweeted_by_user_key, status.quoted_user_key);
}
}

View File

@ -0,0 +1,61 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class RetweetsOfMeLoader(
context: Context,
accountKey: UserKey?,
sinceId: String?,
maxId: String?,
adapterData: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog, credentials: ParcelableCredentials, paging: Paging): ResponseList<Status> {
return microBlog.getRetweetsOfMe(paging)
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, null, status.text_plain,
status.quoted_text_plain, status.spans, status.quoted_spans, status.source,
status.quoted_source, status.retweeted_by_user_key, status.quoted_user_key)
}
}

View File

@ -1,115 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.SearchQuery;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
import java.util.List;
public class TweetSearchLoader extends MicroBlogAPIStatusesLoader {
@Nullable
private final String mQuery;
private final boolean mGapEnabled;
public TweetSearchLoader(final Context context, final UserKey accountKey, @Nullable final String query,
final String sinceId, final String maxId, final int page,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, final boolean fromUser, final boolean makeGap,
boolean loadingMore) {
super(context, accountKey, sinceId, maxId, page, data, savedStatusesArgs, tabPosition,
fromUser, loadingMore);
mQuery = query;
mGapEnabled = makeGap;
}
@NonNull
@Override
public List<? extends Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull final ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
if (mQuery == null) throw new MicroBlogException("Empty query");
final String processedQuery = processQuery(credentials, mQuery);
switch (ParcelableAccountUtils.getAccountType(credentials)) {
case ParcelableAccount.Type.TWITTER: {
final SearchQuery query = new SearchQuery(processedQuery);
query.paging(paging);
return microBlog.search(query);
}
case ParcelableAccount.Type.STATUSNET: {
return microBlog.searchStatuses(processedQuery, paging);
}
case ParcelableAccount.Type.FANFOU: {
return microBlog.searchPublicTimeline(processedQuery, paging);
}
}
throw new MicroBlogException("Not implemented");
}
@NonNull
protected String processQuery(ParcelableCredentials credentials, @NonNull final String query) {
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
return String.format("%s exclude:retweets", query);
}
return query;
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
@Override
protected void processPaging(@NonNull ParcelableCredentials credentials, int loadItemLimit, @NonNull Paging paging) {
if (MicroBlogAPIFactory.isStatusNetCredentials(credentials)) {
paging.setRpp(loadItemLimit);
final int page = getPage();
if (page > 0) {
paging.setPage(page);
}
} else {
super.processPaging(credentials, loadItemLimit, paging);
}
}
@Override
protected boolean isGapEnabled() {
return mGapEnabled;
}
}

View File

@ -0,0 +1,101 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.SearchQuery
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableAccount
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableAccountUtils
import org.mariotaku.twidere.util.InternalTwitterContentUtils
import org.mariotaku.twidere.util.MicroBlogAPIFactory
open class TweetSearchLoader(
context: Context,
accountKey: UserKey?,
private val query: String?,
sinceId: String?,
maxId: String?,
page: Int,
adapterData: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
override val isGapEnabled: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, page, adapterData, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
public override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): List<Status> {
if (query == null) throw MicroBlogException("Empty query")
val processedQuery = processQuery(credentials, query)
when (ParcelableAccountUtils.getAccountType(credentials)) {
ParcelableAccount.Type.TWITTER -> {
val query = SearchQuery(processedQuery)
query.paging(paging)
return microBlog.search(query)
}
ParcelableAccount.Type.STATUSNET -> {
return microBlog.searchStatuses(processedQuery, paging)
}
ParcelableAccount.Type.FANFOU -> {
return microBlog.searchPublicTimeline(processedQuery, paging)
}
}
throw MicroBlogException("Not implemented")
}
protected open fun processQuery(credentials: ParcelableCredentials, query: String): String {
if (MicroBlogAPIFactory.isTwitterCredentials(credentials)) {
return String.format("%s exclude:retweets", query)
}
return query
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, true)
}
override fun processPaging(credentials: ParcelableCredentials, loadItemLimit: Int, paging: Paging) {
if (MicroBlogAPIFactory.isStatusNetCredentials(credentials)) {
paging.setRpp(loadItemLimit)
val page = page
if (page > 0) {
paging.setPage(page)
}
} else {
super.processPaging(credentials, loadItemLimit, paging)
}
}
}

View File

@ -1,92 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class UserFavoritesLoader extends MicroBlogAPIStatusesLoader {
private final UserKey mUserKey;
private final String mUserScreenName;
public UserFavoritesLoader(final Context context, final UserKey accountKey, final UserKey userKey,
final String screenName, final String sinceId, final String maxId,
final int page,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, page, data, savedStatusesArgs, tabPosition, fromUser,
loadingMore);
mUserKey = userKey;
mUserScreenName = screenName;
}
@NonNull
@Override
public ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws MicroBlogException {
if (mUserKey != null) {
return microBlog.getFavorites(mUserKey.getId(), paging);
} else if (mUserScreenName != null) {
return microBlog.getFavoritesByScreenName(mUserScreenName, paging);
}
throw new MicroBlogException("Null user");
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, false);
}
@Override
protected void processPaging(@NonNull ParcelableCredentials credentials, int loadItemLimit, @NonNull Paging paging) {
switch (ParcelableAccountUtils.getAccountType(credentials)) {
case ParcelableAccount.Type.FANFOU: {
paging.setCount(loadItemLimit);
final int page = getPage();
if (page > 0) {
paging.setPage(page);
}
break;
}
default: {
super.processPaging(credentials, loadItemLimit, paging);
break;
}
}
}
}

View File

@ -0,0 +1,82 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableAccount
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableAccountUtils
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class UserFavoritesLoader(
context: Context,
accountKey: UserKey?,
private val userKey: UserKey?,
private val screenName: String?,
sinceId: String?,
maxId: String?,
page: Int,
data: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, page, data, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
public override fun getStatuses(microBlog: MicroBlog, credentials: ParcelableCredentials, paging: Paging): ResponseList<Status> {
if (userKey != null) {
return microBlog.getFavorites(userKey.id, paging)
} else if (screenName != null) {
return microBlog.getFavoritesByScreenName(screenName, paging)
}
throw MicroBlogException("Null user")
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, false)
}
override fun processPaging(credentials: ParcelableCredentials, loadItemLimit: Int, paging: Paging) {
when (ParcelableAccountUtils.getAccountType(credentials)) {
ParcelableAccount.Type.FANFOU -> {
paging.setCount(loadItemLimit)
if (page > 0) {
paging.setPage(page)
}
}
else -> {
super.processPaging(credentials, loadItemLimit, paging)
}
}
}
}

View File

@ -1,76 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class UserListTimelineLoader extends MicroBlogAPIStatusesLoader {
private final UserKey mUserKey;
private final String mScreenName, mListName;
private final String mListId;
public UserListTimelineLoader(final Context context, final UserKey accountKey, final String listId,
final UserKey userKey, final String screenName, final String listName,
final String sinceId, final String maxId, final List<ParcelableStatus> data,
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mListId = listId;
mUserKey = userKey;
mScreenName = screenName;
mListName = listName;
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws MicroBlogException {
if (mListId != null)
return microBlog.getUserListStatuses(mListId, paging);
else if (mListName == null)
throw new MicroBlogException("No list name or id given");
else if (mUserKey != null)
return microBlog.getUserListStatuses(mListName.replace(' ', '-'), mUserKey.getId(), paging);
else if (mScreenName != null)
return microBlog.getUserListStatuses(mListName.replace(' ', '-'), mScreenName, paging);
throw new MicroBlogException("User id or screen name is required for list name");
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
return InternalTwitterContentUtils.isFiltered(database, status, true);
}
}

View File

@ -0,0 +1,76 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class UserListTimelineLoader(
context: Context,
accountKey: UserKey?,
private val listId: String?,
private val userKey: UserKey?,
private val screenName: String?,
private val listName: String?,
sinceId: String?,
maxId: String?,
adapterData: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog, credentials: ParcelableCredentials, paging: Paging): ResponseList<Status> {
when {
listId != null -> {
return microBlog.getUserListStatuses(listId, paging)
}
listName != null && userKey != null -> {
return microBlog.getUserListStatuses(listName.replace(' ', '-'), userKey.id, paging)
}
listName != null && screenName != null -> {
return microBlog.getUserListStatuses(listName.replace(' ', '-'), screenName, paging)
}
else -> {
throw MicroBlogException("User id or screen name is required for list name")
}
}
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
return InternalTwitterContentUtils.isFiltered(database, status, true)
}
}

View File

@ -1,55 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
import java.util.List;
import java.util.Locale;
public class UserMentionsLoader extends TweetSearchLoader {
public UserMentionsLoader(final Context context, final UserKey accountId, final String screenName,
final String maxId, final String sinceId, int page, final List<ParcelableStatus> data,
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser,
boolean makeGap, boolean loadingMore) {
super(context, accountId, screenName, sinceId, maxId, page, data, savedStatusesArgs, tabPosition,
fromUser, makeGap, loadingMore);
}
@NonNull
@Override
protected String processQuery(ParcelableCredentials credentials, @NonNull final String query) {
final UserKey accountKey = getAccountKey();
if (accountKey == null) return query;
final String screenName = query.startsWith("@") ? query.substring(1) : query;
if (MicroBlogAPIFactory.isTwitterCredentials(getContext(), accountKey)) {
return String.format(Locale.ROOT, "to:%s exclude:retweets", screenName);
}
return String.format(Locale.ROOT, "@%s -RT", screenName);
}
}

View File

@ -0,0 +1,53 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.MicroBlogAPIFactory
class UserMentionsLoader(
context: Context,
accountId: UserKey,
screenName: String,
maxId: String?,
sinceId: String?,
page: Int,
data: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
makeGap: Boolean,
loadingMore: Boolean
) : TweetSearchLoader(context, accountId, screenName, sinceId, maxId, page, data, savedStatusesArgs,
tabPosition, fromUser, makeGap, loadingMore) {
override fun processQuery(credentials: ParcelableCredentials, query: String): String {
val accountKey = accountKey ?: return query
val screenName = if (query.startsWith("@")) query.substring(1) else query
if (MicroBlogAPIFactory.isTwitterCredentials(context, accountKey)) {
return "to:$screenName exclude:retweets"
}
return "@$screenName -RT"
}
}

View File

@ -1,83 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import org.mariotaku.microblog.library.MicroBlog;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.microblog.library.twitter.model.Status;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import java.util.List;
public class UserTimelineLoader extends MicroBlogAPIStatusesLoader {
@Nullable
private final UserKey mUserId;
@Nullable
private final String mUserScreenName;
public UserTimelineLoader(final Context context, @Nullable final UserKey accountId,
@Nullable final UserKey userId, @Nullable final String screenName,
final String sinceId, final String maxId,
final List<ParcelableStatus> data, final String[] savedStatusesArgs,
final int tabPosition, boolean fromUser, boolean loadingMore) {
super(context, accountId, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser, loadingMore);
mUserId = userId;
mUserScreenName = screenName;
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(@NonNull final MicroBlog microBlog,
@NonNull ParcelableCredentials credentials,
@NonNull final Paging paging) throws MicroBlogException {
if (mUserId != null) {
return microBlog.getUserTimeline(mUserId.getId(), paging);
} else if (mUserScreenName != null) {
return microBlog.getUserTimelineByScreenName(mUserScreenName, paging);
} else {
throw new MicroBlogException("Invalid user");
}
}
@WorkerThread
@Override
protected boolean shouldFilterStatus(final SQLiteDatabase database, final ParcelableStatus status) {
final UserKey accountId = getAccountKey();
if (accountId != null && mUserId != null && TextUtils.equals(accountId.getId(), mUserId.getId()))
return false;
final UserKey retweetUserId = status.is_retweet ? status.user_key : null;
return InternalTwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
status.quoted_text_plain, status.spans, status.quoted_spans, status.source,
status.quoted_source, null, status.quoted_user_key);
}
}

View File

@ -0,0 +1,74 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.loader
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.support.annotation.WorkerThread
import android.text.TextUtils
import org.mariotaku.microblog.library.MicroBlog
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.model.Paging
import org.mariotaku.microblog.library.twitter.model.ResponseList
import org.mariotaku.microblog.library.twitter.model.Status
import org.mariotaku.twidere.model.ParcelableCredentials
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.InternalTwitterContentUtils
class UserTimelineLoader(
context: Context,
accountId: UserKey?,
private val userId: UserKey?,
private val screenName: String?,
sinceId: String?,
maxId: String?,
data: List<ParcelableStatus>?,
savedStatusesArgs: Array<String>?,
tabPosition: Int,
fromUser: Boolean,
loadingMore: Boolean
) : MicroBlogAPIStatusesLoader(context, accountId, sinceId, maxId, -1, data, savedStatusesArgs, tabPosition, fromUser, loadingMore) {
@Throws(MicroBlogException::class)
override fun getStatuses(microBlog: MicroBlog,
credentials: ParcelableCredentials,
paging: Paging): ResponseList<Status> {
if (userId != null) {
return microBlog.getUserTimeline(userId.id, paging)
} else if (screenName != null) {
return microBlog.getUserTimelineByScreenName(screenName, paging)
} else {
throw MicroBlogException("Invalid user")
}
}
@WorkerThread
override fun shouldFilterStatus(database: SQLiteDatabase, status: ParcelableStatus): Boolean {
val accountId = accountKey
if (accountId != null && userId != null && TextUtils.equals(accountId.id, userId.id))
return false
val retweetUserId = if (status.is_retweet) status.user_key else null
return InternalTwitterContentUtils.isFiltered(database, retweetUserId, status.text_plain,
status.quoted_text_plain, status.spans, status.quoted_spans, status.source,
status.quoted_source, null, status.quoted_user_key)
}
}