supports mastodon user timeline and favorites loader
This commit is contained in:
parent
c9ea5b2890
commit
059c38b6bf
|
@ -21,9 +21,24 @@
|
||||||
|
|
||||||
package org.mariotaku.microblog.library.mastodon.api;
|
package org.mariotaku.microblog.library.mastodon.api;
|
||||||
|
|
||||||
|
import org.mariotaku.microblog.library.MicroBlogException;
|
||||||
|
import org.mariotaku.microblog.library.mastodon.model.Status;
|
||||||
|
import org.mariotaku.microblog.library.twitter.model.Paging;
|
||||||
|
import org.mariotaku.restfu.annotation.method.GET;
|
||||||
|
import org.mariotaku.restfu.annotation.param.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 2017/4/17.
|
* Created by mariotaku on 2017/4/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface FavouriteResources {
|
public interface FavouriteResources {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return An array of {@link Status} favourited by the authenticated user.
|
||||||
|
*/
|
||||||
|
@GET("/v1/favourites")
|
||||||
|
List<Status> getFavourites(@Query Paging paging) throws MicroBlogException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.mariotaku.twidere.model.account;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||||
|
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2017/4/19.
|
||||||
|
*/
|
||||||
|
@ParcelablePlease
|
||||||
|
@JsonObject
|
||||||
|
public class MastodonAccountExtras implements AccountExtras, Parcelable {
|
||||||
|
|
||||||
|
@JsonField(name = "status_text_limit")
|
||||||
|
int statusTextLimit = 500;
|
||||||
|
|
||||||
|
public int getStatusTextLimit() {
|
||||||
|
return statusTextLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusTextLimit(int statusTextLimit) {
|
||||||
|
this.statusTextLimit = statusTextLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
MastodonAccountExtrasParcelablePlease.writeToParcel(this, dest, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<MastodonAccountExtras> CREATOR = new Creator<MastodonAccountExtras>() {
|
||||||
|
public MastodonAccountExtras createFromParcel(Parcel source) {
|
||||||
|
MastodonAccountExtras target = new MastodonAccountExtras();
|
||||||
|
MastodonAccountExtrasParcelablePlease.readFromParcel(target, source);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MastodonAccountExtras[] newArray(int size) {
|
||||||
|
return new MastodonAccountExtras[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ package org.mariotaku.twidere.util.model;
|
||||||
|
|
||||||
import org.mariotaku.twidere.annotation.AccountType;
|
import org.mariotaku.twidere.annotation.AccountType;
|
||||||
import org.mariotaku.twidere.model.account.AccountExtras;
|
import org.mariotaku.twidere.model.account.AccountExtras;
|
||||||
|
import org.mariotaku.twidere.model.account.MastodonAccountExtras;
|
||||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras;
|
import org.mariotaku.twidere.model.account.StatusNetAccountExtras;
|
||||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras;
|
import org.mariotaku.twidere.model.account.TwitterAccountExtras;
|
||||||
import org.mariotaku.twidere.model.account.cred.BasicCredentials;
|
import org.mariotaku.twidere.model.account.cred.BasicCredentials;
|
||||||
|
@ -72,6 +73,9 @@ public class AccountDetailsUtils {
|
||||||
case AccountType.STATUSNET: {
|
case AccountType.STATUSNET: {
|
||||||
return JsonSerializer.parse(json, StatusNetAccountExtras.class);
|
return JsonSerializer.parse(json, StatusNetAccountExtras.class);
|
||||||
}
|
}
|
||||||
|
case AccountType.MASTODON: {
|
||||||
|
return JsonSerializer.parse(json, MastodonAccountExtras.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -6,6 +6,8 @@ import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mariotaku.microblog.library.twitter.model.Status
|
import org.mariotaku.microblog.library.twitter.model.Status
|
||||||
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
|
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.test.R
|
import org.mariotaku.twidere.test.R
|
||||||
import org.mariotaku.twidere.util.JsonSerializer
|
import org.mariotaku.twidere.util.JsonSerializer
|
||||||
|
@ -24,14 +26,12 @@ class ParcelableStatusUtilsTest {
|
||||||
val context = InstrumentationRegistry.getContext()
|
val context = InstrumentationRegistry.getContext()
|
||||||
val status_8754050 = context.resources.openRawResource(R.raw.status_8754050).use {
|
val status_8754050 = context.resources.openRawResource(R.raw.status_8754050).use {
|
||||||
val status = JsonSerializer.parse(it, Status::class.java)
|
val status = JsonSerializer.parse(it, Status::class.java)
|
||||||
return@use ParcelableStatusUtils.fromStatus(status, UserKey("1234567", "gnusocial.de"),
|
return@use status.toParcelable(UserKey("1234567", "gnusocial.de"), AccountType.STATUSNET)
|
||||||
"statusnet", false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val status_9171447 = context.resources.openRawResource(R.raw.status_9171447).use {
|
val status_9171447 = context.resources.openRawResource(R.raw.status_9171447).use {
|
||||||
val status = JsonSerializer.parse(it, Status::class.java)
|
val status = JsonSerializer.parse(it, Status::class.java)
|
||||||
return@use ParcelableStatusUtils.fromStatus(status, UserKey("1234567", "gnusocial.de"),
|
return@use status.toParcelable(UserKey("1234567", "gnusocial.de"), AccountType.STATUSNET)
|
||||||
"statusnet", false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertEquals(status_8754050.text_unescaped, expectedStatusText)
|
Assert.assertEquals(status_8754050.text_unescaped, expectedStatusText)
|
||||||
|
|
|
@ -90,6 +90,7 @@ import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.SingleResponse
|
import org.mariotaku.twidere.model.SingleResponse
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.account.AccountExtras
|
import org.mariotaku.twidere.model.account.AccountExtras
|
||||||
|
import org.mariotaku.twidere.model.account.MastodonAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.cred.*
|
import org.mariotaku.twidere.model.account.cred.*
|
||||||
|
@ -934,7 +935,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
|
|
||||||
credentials.access_token = token.accessToken
|
credentials.access_token = token.accessToken
|
||||||
return SignInResponse(account != null, Credentials.Type.OAUTH2, credentials, user,
|
return SignInResponse(account != null, Credentials.Type.OAUTH2, credentials, user,
|
||||||
color, AccountType.MASTODON, null)
|
color, AccountType.MASTODON, getMastodonAccountExtras(mastodon))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,10 +1273,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
||||||
when (type) {
|
when (type) {
|
||||||
AccountType.STATUSNET -> {
|
AccountType.STATUSNET -> {
|
||||||
return getStatusNetAccountType(twitter)
|
return Pair(type, getStatusNetAccountExtras(twitter))
|
||||||
}
|
}
|
||||||
AccountType.TWITTER -> {
|
AccountType.TWITTER -> {
|
||||||
return getTwitterAccountType(twitter)
|
return Pair(type, getTwitterAccountExtras(twitter))
|
||||||
}
|
}
|
||||||
AccountType.FANFOU -> {
|
AccountType.FANFOU -> {
|
||||||
return Pair(AccountType.FANFOU, null)
|
return Pair(AccountType.FANFOU, null)
|
||||||
|
@ -1289,7 +1290,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
return Pair(AccountType.TWITTER, null)
|
return Pair(AccountType.TWITTER, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getStatusNetAccountType(twitter: MicroBlog): Pair<String, StatusNetAccountExtras> {
|
private fun getStatusNetAccountExtras(twitter: MicroBlog): StatusNetAccountExtras {
|
||||||
// Get StatusNet specific resource
|
// Get StatusNet specific resource
|
||||||
val config = twitter.statusNetConfig
|
val config = twitter.statusNetConfig
|
||||||
val extras = StatusNetAccountExtras()
|
val extras = StatusNetAccountExtras()
|
||||||
|
@ -1297,10 +1298,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
if (site != null) {
|
if (site != null) {
|
||||||
extras.textLimit = site.textLimit
|
extras.textLimit = site.textLimit
|
||||||
}
|
}
|
||||||
return Pair(AccountType.STATUSNET, extras)
|
return extras
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTwitterAccountType(twitter: MicroBlog): Pair<String, TwitterAccountExtras> {
|
private fun getTwitterAccountExtras(twitter: MicroBlog): TwitterAccountExtras {
|
||||||
val extras = TwitterAccountExtras()
|
val extras = TwitterAccountExtras()
|
||||||
try {
|
try {
|
||||||
// Get Twitter official only resource
|
// Get Twitter official only resource
|
||||||
|
@ -1311,7 +1312,11 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
||||||
} catch (e: MicroBlogException) {
|
} catch (e: MicroBlogException) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
return Pair(AccountType.TWITTER, extras)
|
return extras
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMastodonAccountExtras(mastodon: Mastodon): MastodonAccountExtras {
|
||||||
|
return MastodonAccountExtras()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val CustomAPIConfig.signUpUrlOrDefault: String?
|
private val CustomAPIConfig.signUpUrlOrDefault: String?
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.twitter.Validator
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
import org.mariotaku.twidere.model.account.AccountExtras
|
import org.mariotaku.twidere.model.account.AccountExtras
|
||||||
|
import org.mariotaku.twidere.model.account.MastodonAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.cred.Credentials
|
import org.mariotaku.twidere.model.account.cred.Credentials
|
||||||
|
@ -68,6 +69,12 @@ val AccountDetails.textLimit: Int get() {
|
||||||
return extras.textLimit
|
return extras.textLimit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AccountType.MASTODON -> {
|
||||||
|
val extras = this.extras as? MastodonAccountExtras
|
||||||
|
if (extras != null) {
|
||||||
|
return extras.statusTextLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Validator.MAX_TWEET_LENGTH
|
return Validator.MAX_TWEET_LENGTH
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.model.account.AccountExtras
|
import org.mariotaku.twidere.model.account.AccountExtras
|
||||||
|
import org.mariotaku.twidere.model.account.MastodonAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
||||||
import org.mariotaku.twidere.model.account.cred.*
|
import org.mariotaku.twidere.model.account.cred.*
|
||||||
|
@ -23,6 +24,7 @@ import org.mariotaku.twidere.model.util.AccountUtils.ACCOUNT_USER_DATA_KEYS
|
||||||
import org.mariotaku.twidere.util.JsonSerializer
|
import org.mariotaku.twidere.util.JsonSerializer
|
||||||
import org.mariotaku.twidere.util.ParseUtils
|
import org.mariotaku.twidere.util.ParseUtils
|
||||||
import org.mariotaku.twidere.util.TwitterContentUtils
|
import org.mariotaku.twidere.util.TwitterContentUtils
|
||||||
|
import org.mariotaku.twidere.util.model.AccountDetailsUtils
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
@ -76,15 +78,7 @@ fun Account.getPosition(am: AccountManager): Int {
|
||||||
|
|
||||||
fun Account.getAccountExtras(am: AccountManager): AccountExtras? {
|
fun Account.getAccountExtras(am: AccountManager): AccountExtras? {
|
||||||
val json = AccountDataQueue.getUserData(am, this, ACCOUNT_USER_DATA_EXTRAS) ?: return null
|
val json = AccountDataQueue.getUserData(am, this, ACCOUNT_USER_DATA_EXTRAS) ?: return null
|
||||||
when (getAccountType(am)) {
|
return AccountDetailsUtils.parseAccountExtras(json, getAccountType(am))
|
||||||
AccountType.TWITTER -> {
|
|
||||||
return JsonSerializer.parse(json, TwitterAccountExtras::class.java)
|
|
||||||
}
|
|
||||||
AccountType.STATUSNET -> {
|
|
||||||
return JsonSerializer.parse(json, StatusNetAccountExtras::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AccountType
|
@AccountType
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.mariotaku.twidere.extension.model
|
||||||
|
|
||||||
|
import org.mariotaku.twidere.model.UserKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mariotaku on 2017/4/19.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private const val mastodonPlaceholderId = "#mastodon*placeholder#"
|
||||||
|
|
||||||
|
val UserKey.isMastodonPlaceholder get() = mastodonPlaceholderId == id && host != null
|
|
@ -25,4 +25,7 @@ import org.mariotaku.twidere.util.HtmlEscapeHelper
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 2017/4/19.
|
* Created by mariotaku on 2017/4/19.
|
||||||
*/
|
*/
|
||||||
val Application.sourceHtml get() = "<a href='${HtmlEscapeHelper.escape(website)}'>${HtmlEscapeHelper.escape(name)}</a>"
|
val Application.sourceHtml: String get() {
|
||||||
|
if (website == null) return HtmlEscapeHelper.escape(name)
|
||||||
|
return "<a href='${HtmlEscapeHelper.escape(website)}'>${HtmlEscapeHelper.escape(name)}</a>"
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_FROM_USER
|
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_FROM_USER
|
||||||
import org.mariotaku.twidere.extension.reachingEnd
|
import org.mariotaku.twidere.extension.reachingEnd
|
||||||
import org.mariotaku.twidere.extension.reachingStart
|
import org.mariotaku.twidere.extension.reachingStart
|
||||||
import org.mariotaku.twidere.loader.RequestStatusesLoader
|
import org.mariotaku.twidere.loader.AbsRequestStatusesLoader
|
||||||
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
import org.mariotaku.twidere.loader.iface.IExtendedLoader
|
||||||
import org.mariotaku.twidere.model.ParcelableStatus
|
import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
import org.mariotaku.twidere.util.IntentUtils
|
import org.mariotaku.twidere.util.IntentUtils
|
||||||
|
@ -136,7 +136,7 @@ abstract class AbsMediaStatusesFragment : AbsContentRecyclerViewFragment<Stagger
|
||||||
|
|
||||||
protected open fun hasMoreData(loader: Loader<List<ParcelableStatus>?>,
|
protected open fun hasMoreData(loader: Loader<List<ParcelableStatus>?>,
|
||||||
data: List<ParcelableStatus>?, changed: Boolean): Boolean {
|
data: List<ParcelableStatus>?, changed: Boolean): Boolean {
|
||||||
if (loader !is RequestStatusesLoader) return false
|
if (loader !is AbsRequestStatusesLoader) return false
|
||||||
val maxId = loader.maxId?.takeIf(String::isNotEmpty)
|
val maxId = loader.maxId?.takeIf(String::isNotEmpty)
|
||||||
val sinceId = loader.sinceId?.takeIf(String::isNotEmpty)
|
val sinceId = loader.sinceId?.takeIf(String::isNotEmpty)
|
||||||
if (sinceId == null && maxId != null) {
|
if (sinceId == null && maxId != null) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.mariotaku.twidere.R
|
||||||
import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter
|
import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter
|
||||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||||
import org.mariotaku.twidere.loader.RequestStatusesLoader
|
import org.mariotaku.twidere.loader.AbsRequestStatusesLoader
|
||||||
import org.mariotaku.twidere.model.BaseRefreshTaskParam
|
import org.mariotaku.twidere.model.BaseRefreshTaskParam
|
||||||
import org.mariotaku.twidere.model.ParcelableStatus
|
import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
import org.mariotaku.twidere.model.RefreshTaskParam
|
import org.mariotaku.twidere.model.RefreshTaskParam
|
||||||
|
@ -132,7 +132,7 @@ abstract class ParcelableStatusesFragment : AbsStatusesFragment() {
|
||||||
setLoadMoreIndicatorPosition(ILoadMoreSupportAdapter.NONE)
|
setLoadMoreIndicatorPosition(ILoadMoreSupportAdapter.NONE)
|
||||||
if (adapter.itemCount > 0) {
|
if (adapter.itemCount > 0) {
|
||||||
showContent()
|
showContent()
|
||||||
} else if (loader is RequestStatusesLoader) {
|
} else if (loader is AbsRequestStatusesLoader) {
|
||||||
val e = loader.exception
|
val e = loader.exception
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
showError(R.drawable.ic_info_error_generic, Utils.getErrorMessage(context, e) ?:
|
showError(R.drawable.ic_info_error_generic, Utils.getErrorMessage(context, e) ?:
|
||||||
|
|
|
@ -1136,13 +1136,18 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TAB_TYPE_FAVORITES -> {
|
TAB_TYPE_FAVORITES -> {
|
||||||
if (preferences[iWantMyStarsBackKey]) {
|
if (user.favorites_count < 0) {
|
||||||
|
if (preferences[iWantMyStarsBackKey]) {
|
||||||
|
actionBar.setSubtitle(R.string.title_favorites)
|
||||||
|
} else {
|
||||||
|
actionBar.setSubtitle(R.string.title_likes)
|
||||||
|
}
|
||||||
|
} else if (preferences[iWantMyStarsBackKey]) {
|
||||||
actionBar.subtitle = resources.getQuantityString(R.plurals.N_favorites,
|
actionBar.subtitle = resources.getQuantityString(R.plurals.N_favorites,
|
||||||
user.favorites_count.toInt(), user.favorites_count)
|
user.favorites_count.toInt(), user.favorites_count)
|
||||||
} else {
|
} else {
|
||||||
actionBar.subtitle = resources.getQuantityString(R.plurals.N_likes,
|
actionBar.subtitle = resources.getQuantityString(R.plurals.N_likes,
|
||||||
user.favorites_count.toInt(), user.favorites_count)
|
user.favorites_count.toInt(), user.favorites_count)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -48,7 +48,7 @@ import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
abstract class RequestStatusesLoader(
|
abstract class AbsRequestStatusesLoader(
|
||||||
context: Context,
|
context: Context,
|
||||||
val accountKey: UserKey?,
|
val accountKey: UserKey?,
|
||||||
val sinceId: String?,
|
val sinceId: String?,
|
|
@ -36,7 +36,7 @@ import org.mariotaku.twidere.model.util.AccountUtils
|
||||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class MicroBlogAPIUsersLoader(
|
abstract class AbsRequestUsersLoader(
|
||||||
context: Context,
|
context: Context,
|
||||||
val accountKey: UserKey?,
|
val accountKey: UserKey?,
|
||||||
data: List<ParcelableUser>?,
|
data: List<ParcelableUser>?,
|
|
@ -48,7 +48,7 @@ class ConversationLoader(
|
||||||
adapterData: List<ParcelableStatus>?,
|
adapterData: List<ParcelableStatus>?,
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, status.account_key, sinceId, maxId, -1, adapterData, null,
|
) : AbsRequestStatusesLoader(context, status.account_key, sinceId, maxId, -1, adapterData, null,
|
||||||
-1, fromUser, loadingMore) {
|
-1, fromUser, loadingMore) {
|
||||||
|
|
||||||
private val status = ParcelUtils.clone(status)
|
private val status = ParcelUtils.clone(status)
|
||||||
|
|
|
@ -37,7 +37,7 @@ abstract class CursorSupportUsersLoader(
|
||||||
accountKey: UserKey?,
|
accountKey: UserKey?,
|
||||||
data: List<ParcelableUser>?,
|
data: List<ParcelableUser>?,
|
||||||
fromUser: Boolean
|
fromUser: Boolean
|
||||||
) : MicroBlogAPIUsersLoader(context, accountKey, data, fromUser), ICursorSupportLoader {
|
) : AbsRequestUsersLoader(context, accountKey, data, fromUser), ICursorSupportLoader {
|
||||||
|
|
||||||
var page = -1
|
var page = -1
|
||||||
override var cursor: Long = 0
|
override var cursor: Long = 0
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.mariotaku.microblog.library.MicroBlog
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
import org.mariotaku.microblog.library.twitter.model.Status
|
import org.mariotaku.microblog.library.twitter.model.Status
|
||||||
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
@ -33,23 +34,16 @@ import org.mariotaku.twidere.model.ParcelableStatus
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.util.InternalTwitterContentUtils
|
import org.mariotaku.twidere.util.InternalTwitterContentUtils
|
||||||
|
|
||||||
class GroupTimelineLoader(
|
class GroupTimelineLoader(context: Context, accountKey: UserKey?, private val groupId: String?,
|
||||||
context: Context,
|
private val groupName: String?, sinceId: String?, maxId: String?,
|
||||||
accountKey: UserKey?,
|
adapterData: List<ParcelableStatus>?, savedStatusesArgs: Array<String>?,
|
||||||
private val groupId: String?,
|
tabPosition: Int, fromUser: Boolean, loadingMore: Boolean) : AbsRequestStatusesLoader(context,
|
||||||
private val groupName: String?,
|
accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs, tabPosition, fromUser,
|
||||||
sinceId: String?,
|
loadingMore) {
|
||||||
maxId: String?,
|
|
||||||
adapterData: List<ParcelableStatus>?,
|
|
||||||
savedStatusesArgs: Array<String>?,
|
|
||||||
tabPosition: Int,
|
|
||||||
fromUser: Boolean,
|
|
||||||
loadingMore: Boolean
|
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
|
|
||||||
tabPosition, fromUser, loadingMore) {
|
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
override fun getStatuses(account: AccountDetails, paging: Paging): List<ParcelableStatus> {
|
override fun getStatuses(account: AccountDetails, paging: Paging): List<ParcelableStatus> {
|
||||||
|
if (account.type != AccountType.STATUSNET) throw MicroBlogException("Not supported")
|
||||||
return getMicroBlogStatuses(account, paging).map {
|
return getMicroBlogStatuses(account, paging).map {
|
||||||
it.toParcelable(account.key, account.type, profileImageSize)
|
it.toParcelable(account.key, account.type, profileImageSize)
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ open class MediaStatusesSearchLoader(
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
override val isGapEnabled: Boolean,
|
override val isGapEnabled: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, page, adapterData, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, page, adapterData, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
|
|
|
@ -50,7 +50,7 @@ class MediaTimelineLoader(
|
||||||
tabPosition: Int,
|
tabPosition: Int,
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
private var user: User? = null
|
private var user: User? = null
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.mariotaku.twidere.TwidereConstants.*
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
import org.mariotaku.twidere.annotation.Referral
|
import org.mariotaku.twidere.annotation.Referral
|
||||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||||
|
import org.mariotaku.twidere.extension.model.isMastodonPlaceholder
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
import org.mariotaku.twidere.model.ParcelableUser
|
import org.mariotaku.twidere.model.ParcelableUser
|
||||||
|
@ -158,8 +159,14 @@ class ParcelableUserLoader(
|
||||||
|
|
||||||
private fun showMastodonUser(details: AccountDetails): ParcelableUser {
|
private fun showMastodonUser(details: AccountDetails): ParcelableUser {
|
||||||
val mastodon = details.newMicroBlogInstance(context, Mastodon::class.java)
|
val mastodon = details.newMicroBlogInstance(context, Mastodon::class.java)
|
||||||
if (userKey != null) return mastodon.getAccount(userKey.id).toParcelable(details.key)
|
if (userKey == null) throw MicroBlogException("Invalid user id")
|
||||||
throw MicroBlogException("No user id")
|
if (!userKey.isMastodonPlaceholder) {
|
||||||
|
return mastodon.getAccount(userKey.id).toParcelable(details.key)
|
||||||
|
}
|
||||||
|
if (screenName == null) throw MicroBlogException("Screen name required")
|
||||||
|
val resultItem = mastodon.searchAccounts("$screenName@${userKey.host}").firstOrNull() ?:
|
||||||
|
throw MicroBlogException("User not found")
|
||||||
|
return resultItem.toParcelable(details.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showMicroBlogUser(details: AccountDetails): ParcelableUser {
|
private fun showMicroBlogUser(details: AccountDetails): ParcelableUser {
|
||||||
|
|
|
@ -43,7 +43,7 @@ class PublicTimelineLoader(
|
||||||
tabPosition: Int,
|
tabPosition: Int,
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
|
|
|
@ -50,7 +50,7 @@ open class TweetSearchLoader(
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
override val isGapEnabled: Boolean,
|
override val isGapEnabled: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, page, adapterData, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, page, adapterData, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
|
|
|
@ -24,10 +24,12 @@ import android.database.sqlite.SQLiteDatabase
|
||||||
import android.support.annotation.WorkerThread
|
import android.support.annotation.WorkerThread
|
||||||
import org.mariotaku.microblog.library.MicroBlog
|
import org.mariotaku.microblog.library.MicroBlog
|
||||||
import org.mariotaku.microblog.library.MicroBlogException
|
import org.mariotaku.microblog.library.MicroBlogException
|
||||||
|
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||||
import org.mariotaku.microblog.library.twitter.model.Paging
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||||
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
import org.mariotaku.microblog.library.twitter.model.ResponseList
|
||||||
import org.mariotaku.microblog.library.twitter.model.Status
|
import org.mariotaku.microblog.library.twitter.model.Status
|
||||||
import org.mariotaku.twidere.annotation.AccountType
|
import org.mariotaku.twidere.annotation.AccountType
|
||||||
|
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
@ -48,11 +50,16 @@ class UserFavoritesLoader(
|
||||||
tabPosition: Int,
|
tabPosition: Int,
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, page, data, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, page, data, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
override fun getStatuses(account: AccountDetails, paging: Paging): List<ParcelableStatus> {
|
override fun getStatuses(account: AccountDetails, paging: Paging): List<ParcelableStatus> {
|
||||||
|
when (account.type) {
|
||||||
|
AccountType.MASTODON -> {
|
||||||
|
return getMastodonStatuses(account, paging)
|
||||||
|
}
|
||||||
|
}
|
||||||
return getMicroBlogStatuses(account, paging).map {
|
return getMicroBlogStatuses(account, paging).map {
|
||||||
it.toParcelable(account.key, account.type, profileImageSize)
|
it.toParcelable(account.key, account.type, profileImageSize)
|
||||||
}
|
}
|
||||||
|
@ -86,4 +93,15 @@ class UserFavoritesLoader(
|
||||||
}
|
}
|
||||||
throw MicroBlogException("Null user")
|
throw MicroBlogException("Null user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getMastodonStatuses(account: AccountDetails, paging: Paging): List<ParcelableStatus> {
|
||||||
|
if (userKey != null && userKey != account.key) {
|
||||||
|
throw MicroBlogException("Only current account favorites is supported")
|
||||||
|
}
|
||||||
|
if (screenName != null && !screenName.equals(account.user?.screen_name, ignoreCase = true)) {
|
||||||
|
throw MicroBlogException("Only current account favorites is supported")
|
||||||
|
}
|
||||||
|
val mastodon = account.newMicroBlogInstance(context, Mastodon::class.java)
|
||||||
|
return mastodon.getFavourites(paging).map { it.toParcelable(account.key) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class UserListTimelineLoader(
|
||||||
tabPosition: Int,
|
tabPosition: Int,
|
||||||
fromUser: Boolean,
|
fromUser: Boolean,
|
||||||
loadingMore: Boolean
|
loadingMore: Boolean
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, -1, adapterData, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
|
|
|
@ -36,7 +36,7 @@ open class UserSearchLoader(
|
||||||
val page: Int,
|
val page: Int,
|
||||||
data: List<ParcelableUser>?,
|
data: List<ParcelableUser>?,
|
||||||
fromUser: Boolean
|
fromUser: Boolean
|
||||||
) : MicroBlogAPIUsersLoader(context, accountKey, data, fromUser) {
|
) : AbsRequestUsersLoader(context, accountKey, data, fromUser) {
|
||||||
|
|
||||||
@Throws(MicroBlogException::class)
|
@Throws(MicroBlogException::class)
|
||||||
override fun getUsers(twitter: MicroBlog, details: AccountDetails): List<User> {
|
override fun getUsers(twitter: MicroBlog, details: AccountDetails): List<User> {
|
||||||
|
|
|
@ -69,7 +69,7 @@ class UserTimelineLoader(
|
||||||
loadingMore: Boolean,
|
loadingMore: Boolean,
|
||||||
val pinnedStatusIds: Array<String>?,
|
val pinnedStatusIds: Array<String>?,
|
||||||
val timelineFilter: UserTimelineFilter? = null
|
val timelineFilter: UserTimelineFilter? = null
|
||||||
) : RequestStatusesLoader(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs,
|
) : AbsRequestStatusesLoader(context, accountKey, sinceId, maxId, -1, data, savedStatusesArgs,
|
||||||
tabPosition, fromUser, loadingMore) {
|
tabPosition, fromUser, loadingMore) {
|
||||||
|
|
||||||
private val pinnedStatusesRef = AtomicReference<List<ParcelableStatus>>()
|
private val pinnedStatusesRef = AtomicReference<List<ParcelableStatus>>()
|
||||||
|
|
|
@ -101,7 +101,7 @@ interface GeneralComponent {
|
||||||
|
|
||||||
fun inject(provider: CacheProvider)
|
fun inject(provider: CacheProvider)
|
||||||
|
|
||||||
fun inject(loader: RequestStatusesLoader)
|
fun inject(loader: AbsRequestStatusesLoader)
|
||||||
|
|
||||||
fun inject(activity: MediaViewerActivity)
|
fun inject(activity: MediaViewerActivity)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue