improved api instance creation

This commit is contained in:
Mariotaku Lee 2017-02-11 17:03:35 +08:00
parent d819fa9bd1
commit 64b05c6bc1
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
12 changed files with 211 additions and 73 deletions

View File

@ -21,10 +21,14 @@
package org.mariotaku.microblog.library.fanfou.api;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.fanfou.model.Conversation;
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
import org.mariotaku.microblog.library.twitter.model.Paging;
import org.mariotaku.microblog.library.twitter.model.ResponseList;
import org.mariotaku.restfu.annotation.method.GET;
import org.mariotaku.restfu.annotation.method.POST;
import org.mariotaku.restfu.annotation.param.Param;
import org.mariotaku.microblog.library.MicroBlogException;
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
/**
* Created by mariotaku on 16/3/31.
@ -41,4 +45,7 @@ public interface DirectMessagesResources {
DirectMessage sendFanfouDirectMessage(@Param("user") String user, @Param("text") String text)
throws MicroBlogException;
@GET("/direct_messages/conversation_list.json")
ResponseList<Conversation> getConversationList(@Param Paging paging)
throws MicroBlogException;
}

View File

@ -0,0 +1,99 @@
/*
* 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.microblog.library.fanfou.model;
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;
import org.mariotaku.microblog.library.twitter.model.DirectMessage;
/**
* Fanfou DM conversation object
* <p>
* Created by mariotaku on 2017/2/11.
*
* @see <a href="https://github.com/FanfouAPI/FanFouAPIDoc/wiki/direct-messages.conversation-list">GET /privete_messages/conversation_list</a>
*/
@ParcelablePlease
@JsonObject
public class Conversation implements Parcelable {
@JsonField(name = "dm")
DirectMessage dm;
@JsonField(name = "otherid")
String otherId;
@JsonField(name = "msg_num")
int messageNumber;
@JsonField(name = "new_conv")
boolean newConversation;
public DirectMessage getDm() {
return dm;
}
public int getMessageNumber() {
return messageNumber;
}
public boolean isNewConversation() {
return newConversation;
}
public String getOtherId() {
return otherId;
}
@Override
public String toString() {
return "Conversation{" +
"dm=" + dm +
", otherId='" + otherId + '\'' +
", messageNumber=" + messageNumber +
", newConversation=" + newConversation +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
ConversationParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
public Conversation createFromParcel(Parcel source) {
Conversation target = new Conversation();
ConversationParcelablePlease.readFromParcel(target, source);
return target;
}
public Conversation[] newArray(int size) {
return new Conversation[size];
}
};
}

View File

@ -101,8 +101,8 @@ public class MicroBlogAPIFactory implements TwidereConstants {
final Credentials credentials = AccountExtensionsKt.getCredentials(account, am);
final String accountType = AccountExtensionsKt.getAccountType(account, am);
final HashMap<String, String> extraParams = getExtraParams(accountType, true, true);
return CredentialsExtensionsKt.newMicroBlogInstance(credentials, context,
AccountType.TWITTER.equals(accountType), extraParams, MicroBlog.class);
return CredentialsExtensionsKt.newMicroBlogInstance(credentials, context, accountType,
extraParams, MicroBlog.class);
}
@NonNull

View File

@ -203,7 +203,7 @@ class BrowserSignInActivity : BaseActivity() {
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiConfig.apiUrlFormat,
apiConfig.isSameOAuthUrl)
val auth = OAuthAuthorization(apiConfig.consumerKey, apiConfig.consumerSecret)
val oauth = newMicroBlogInstance(activity, endpoint, auth, true, null,
val oauth = newMicroBlogInstance(activity, endpoint, auth, apiConfig.type, null,
TwitterOAuth::class.java)
return SingleResponse(oauth.getRequestToken(TwidereConstants.OAUTH_CALLBACK_OOB))
} catch (e: MicroBlogException) {

View File

@ -596,6 +596,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
apiConfig.isSameOAuthUrl)
val oauth = newMicroBlogInstance(context, endpoint = endpoint,
auth = OAuthAuthorization(apiConfig.consumerKey, apiConfig.consumerSecret),
accountType = apiConfig.type,
cls = TwitterOAuth::class.java)
val accessToken: OAuthToken
if (oauthVerifier != null) {
@ -609,7 +610,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
apiConfig.isSameOAuthUrl)
val twitter = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
cls = MicroBlog::class.java)
accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials()
var color = analyseUserProfileColor(apiUser)
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
@ -845,7 +846,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
val auth = OAuthAuthorization(apiConfig.consumerKey,
apiConfig.consumerSecret)
val oauth = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = TwitterOAuth::class.java)
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
val authenticator = OAuthPasswordAuthenticator(oauth,
verificationCallback, userAgent)
val accessToken = authenticator.getOAuthAccessToken(username, password)
@ -862,7 +863,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
var auth = OAuthAuthorization(apiConfig.consumerKey,
apiConfig.consumerSecret)
val oauth = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = TwitterOAuth::class.java)
accountType = apiConfig.type, cls = TwitterOAuth::class.java)
val accessToken = oauth.getAccessToken(username, password)
var userId: String? = accessToken.userId
if (userId == null) {
@ -872,7 +873,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
endpoint = MicroBlogAPIFactory.getOAuthRestEndpoint(apiUrlFormat, apiConfig.isSameOAuthUrl,
apiConfig.isNoVersionSuffix)
val microBlog = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = MicroBlog::class.java)
accountType = apiConfig.type, cls = MicroBlog::class.java)
userId = microBlog.verifyCredentials().id
}
return getOAuthSignInResponse(activity, accessToken, userId!!, Credentials.Type.XAUTH)
@ -886,7 +887,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
versionSuffix))
val auth = BasicAuthorization(username, password)
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = MicroBlog::class.java)
accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser: User
try {
apiUser = twitter.verifyCredentials()
@ -927,7 +928,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
versionSuffix))
val auth = EmptyAuthorization()
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = MicroBlog::class.java)
accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials()
val userId = apiUser.id!!
var color = analyseUserProfileColor(apiUser)
@ -949,14 +950,14 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDi
@Throws(MicroBlogException::class)
private fun getOAuthSignInResponse(activity: SignInActivity,
accessToken: OAuthToken,
userId: String, @Credentials.Type authType: String): SignInResponse {
accessToken: OAuthToken,
userId: String, @Credentials.Type authType: String): SignInResponse {
val auth = OAuthAuthorization(apiConfig.consumerKey,
apiConfig.consumerSecret, accessToken)
val endpoint = MicroBlogAPIFactory.getOAuthRestEndpoint(apiUrlFormat,
apiConfig.isSameOAuthUrl, apiConfig.isNoVersionSuffix)
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
cls = MicroBlog::class.java)
accountType = apiConfig.type, cls = MicroBlog::class.java)
val apiUser = twitter.verifyCredentials()
var color = analyseUserProfileColor(apiUser)
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)

View File

@ -38,10 +38,11 @@ fun <T> AccountDetails.newMicroBlogInstance(
context: Context,
includeEntities: Boolean = true,
includeRetweets: Boolean = true,
extraRequestParams: Map<String, String>? = MicroBlogAPIFactory.getExtraParams(type, includeEntities, includeRetweets),
extraRequestParams: Map<String, String>? = MicroBlogAPIFactory.getExtraParams(type,
includeEntities, includeRetweets),
cls: Class<T>
): T {
return credentials.newMicroBlogInstance(context, type == AccountType.TWITTER, extraRequestParams, cls)
return credentials.newMicroBlogInstance(context, type, extraRequestParams, cls)
}
val AccountDetails.is_oauth: Boolean

View File

@ -11,11 +11,11 @@ import org.mariotaku.microblog.library.twitter.util.TwitterConverterFactory
import org.mariotaku.restfu.RestAPIFactory
import org.mariotaku.restfu.http.Authorization
import org.mariotaku.restfu.http.Endpoint
import org.mariotaku.restfu.http.SimpleValueMap
import org.mariotaku.restfu.oauth.OAuthAuthorization
import org.mariotaku.restfu.oauth.OAuthEndpoint
import org.mariotaku.restfu.oauth.OAuthToken
import org.mariotaku.twidere.TwidereConstants.DEFAULT_TWITTER_API_URL_FORMAT
import org.mariotaku.twidere.annotation.AccountType
import org.mariotaku.twidere.model.ConsumerKeyType
import org.mariotaku.twidere.model.account.cred.BasicCredentials
import org.mariotaku.twidere.model.account.cred.Credentials
@ -23,6 +23,7 @@ import org.mariotaku.twidere.model.account.cred.EmptyCredentials
import org.mariotaku.twidere.model.account.cred.OAuthCredentials
import org.mariotaku.twidere.util.HttpClientFactory
import org.mariotaku.twidere.util.MicroBlogAPIFactory
import org.mariotaku.twidere.util.MicroBlogAPIFactory.sFanfouConstantPool
import org.mariotaku.twidere.util.MicroBlogAPIFactory.sTwitterConstantPool
import org.mariotaku.twidere.util.TwitterContentUtils
import org.mariotaku.twidere.util.dagger.DependencyHolder
@ -100,24 +101,15 @@ fun Credentials.getEndpoint(cls: Class<*>): Endpoint {
return Endpoint(endpointUrl)
}
fun <T> Credentials.newMicroBlogInstance(
context: Context,
twitterExtraQueries: Boolean = true,
extraRequestParams: Map<String, String>? = null,
cls: Class<T>
): T {
return newMicroBlogInstance(context, getEndpoint(cls), getAuthorization(),
twitterExtraQueries, extraRequestParams, cls)
fun <T> Credentials.newMicroBlogInstance(context: Context, @AccountType accountType: String? = null,
extraRequestParams: Map<String, String>? = null, cls: Class<T>): T {
return newMicroBlogInstance(context, getEndpoint(cls), getAuthorization(), accountType,
extraRequestParams, cls)
}
fun <T> newMicroBlogInstance(
context: Context,
endpoint: Endpoint,
auth: Authorization,
twitterExtraQueries: Boolean = true,
extraRequestParams: Map<String, String>? = null,
cls: Class<T>
): T {
fun <T> newMicroBlogInstance(context: Context, endpoint: Endpoint, auth: Authorization,
@AccountType accountType: String? = null, extraRequestParams: Map<String, String>? = null,
cls: Class<T>): T {
val factory = RestAPIFactory<MicroBlogException>()
val userAgent: String
if (auth is OAuthAuthorization) {
@ -149,10 +141,13 @@ fun <T> newMicroBlogInstance(
}
factory.setAuthorization(auth)
factory.setEndpoint(endpoint)
if (twitterExtraQueries) {
factory.setConstantPool(sTwitterConstantPool)
} else {
factory.setConstantPool(SimpleValueMap())
when (accountType) {
AccountType.TWITTER -> {
factory.setConstantPool(sTwitterConstantPool)
}
AccountType.FANFOU -> {
factory.setConstantPool(sFanfouConstantPool)
}
}
val converterFactory = TwitterConverterFactory()
factory.setRestConverterFactory(converterFactory)

View File

@ -19,9 +19,17 @@
package org.mariotaku.twidere.view.holder.message
import android.os.Build
import android.support.v4.view.GravityCompat
import android.support.v7.widget.RecyclerView
import android.text.format.DateUtils
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import org.mariotaku.twidere.adapter.MessagesConversationAdapter
import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.model.ParcelableMessage
/**
@ -30,7 +38,41 @@ import org.mariotaku.twidere.model.ParcelableMessage
abstract class AbsMessageViewHolder(itemView: View, val adapter: MessagesConversationAdapter) : RecyclerView.ViewHolder(itemView) {
open fun display(message: ParcelableMessage, showDate: Boolean) {
protected abstract val date: TextView
protected abstract val messageContent: View
open fun display(message: ParcelableMessage, showDate: Boolean) {
setMessageContentGravity(messageContent, message.is_outgoing)
if (showDate) {
date.visibility = View.VISIBLE
date.text = DateUtils.getRelativeTimeSpanString(message.timestamp, System.currentTimeMillis(),
DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_SHOW_DATE)
} else {
date.visibility = View.GONE
}
}
open fun setMessageContentGravity(view: View, outgoing: Boolean) {
val lp = view.layoutParams
when (lp) {
is FrameLayout.LayoutParams -> {
lp.gravity = if (outgoing) GravityCompat.END else GravityCompat.START
}
is LinearLayout.LayoutParams -> {
lp.gravity = if (outgoing) GravityCompat.END else GravityCompat.START
}
is RelativeLayout.LayoutParams -> {
val endRule = if (outgoing) 1 else 0
val startRule = if (outgoing) 0 else 1
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
lp.addRule(RelativeLayout.ALIGN_PARENT_START, startRule)
lp.addRule(RelativeLayout.ALIGN_PARENT_END, endRule)
} else {
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, startRule)
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, endRule)
}
}
}
}
}

View File

@ -19,12 +19,9 @@
package org.mariotaku.twidere.view.holder.message
import android.support.v4.view.GravityCompat
import android.text.SpannableStringBuilder
import android.text.format.DateUtils
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import kotlinx.android.synthetic.main.list_item_message_conversation_text.view.*
import org.mariotaku.ktextension.empty
import org.mariotaku.ktextension.isNullOrEmpty
@ -35,6 +32,7 @@ import org.mariotaku.twidere.extension.model.applyTo
import org.mariotaku.twidere.extension.model.timestamp
import org.mariotaku.twidere.model.ParcelableMessage
import org.mariotaku.twidere.model.SpanItem
import org.mariotaku.twidere.view.FixedTextView
/**
* Created by mariotaku on 2017/2/9.
@ -42,11 +40,12 @@ import org.mariotaku.twidere.model.SpanItem
class MessageViewHolder(itemView: View, adapter: MessagesConversationAdapter) : AbsMessageViewHolder(itemView, adapter) {
private val date by lazy { itemView.date }
override val date: FixedTextView by lazy { itemView.date }
override val messageContent: MessageBubbleView by lazy { itemView.messageContent }
private val text by lazy { itemView.text }
private val time by lazy { itemView.time }
private val mediaPreview by lazy { itemView.mediaPreview }
private val messageContent by lazy { itemView.messageContent }
init {
val textSize = adapter.textSize
@ -58,15 +57,7 @@ class MessageViewHolder(itemView: View, adapter: MessagesConversationAdapter) :
override fun display(message: ParcelableMessage, showDate: Boolean) {
super.display(message, showDate)
setOutgoingStatus(messageContent, message.is_outgoing)
if (showDate) {
date.visibility = View.VISIBLE
date.text = DateUtils.getRelativeTimeSpanString(message.timestamp, System.currentTimeMillis(),
DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_SHOW_DATE)
} else {
date.visibility = View.GONE
}
messageContent.setOutgoing(message.is_outgoing)
// Loop through text and spans to found non-space char count
val hideText = run {
@ -121,21 +112,8 @@ class MessageViewHolder(itemView: View, adapter: MessagesConversationAdapter) :
companion object {
const val layoutResource = R.layout.list_item_message_conversation_text
fun setOutgoingStatus(view: MessageBubbleView, outgoing: Boolean) {
view.setCaretPosition(if (outgoing) MessageBubbleView.BOTTOM_END else MessageBubbleView.BOTTOM_START)
setMessageContentGravity(view, outgoing)
}
fun setMessageContentGravity(view: View, outgoing: Boolean) {
val lp = view.layoutParams
when (lp) {
is FrameLayout.LayoutParams -> {
lp.gravity = if (outgoing) GravityCompat.END else GravityCompat.START
}
is LinearLayout.LayoutParams -> {
lp.gravity = if (outgoing) GravityCompat.END else GravityCompat.START
}
}
fun MessageBubbleView.setOutgoing(outgoing: Boolean) {
setCaretPosition(if (outgoing) MessageBubbleView.BOTTOM_END else MessageBubbleView.BOTTOM_START)
}
}
}

View File

@ -20,11 +20,13 @@
package org.mariotaku.twidere.view.holder.message
import android.view.View
import android.widget.RelativeLayout
import kotlinx.android.synthetic.main.list_item_message_conversation_sticker.view.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.MessagesConversationAdapter
import org.mariotaku.twidere.model.ParcelableMessage
import org.mariotaku.twidere.model.message.StickerExtras
import org.mariotaku.twidere.view.FixedTextView
/**
* Created by mariotaku on 2017/2/9.
@ -32,12 +34,13 @@ import org.mariotaku.twidere.model.message.StickerExtras
class StickerMessageViewHolder(itemView: View, adapter: MessagesConversationAdapter) : AbsMessageViewHolder(itemView, adapter) {
private val messageContent by lazy { itemView.messageContent }
override val date: FixedTextView by lazy { itemView.date }
override val messageContent: RelativeLayout by lazy { itemView.messageContent }
private val stickerIcon by lazy { itemView.stickerIcon }
override fun display(message: ParcelableMessage, showDate: Boolean) {
super.display(message, showDate)
MessageViewHolder.setMessageContentGravity(messageContent, message.is_outgoing)
val extras = message.extras as StickerExtras
adapter.mediaLoader.displayStickerImage(stickerIcon, extras.url)
}

View File

@ -18,16 +18,28 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<FrameLayout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.FixedTextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="@dimen/element_spacing_normal"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorTertiary"
tools:text="Yesterday"/>
<RelativeLayout
android:id="@+id/messageContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_below="@+id/date">
<ImageView
android:id="@+id/stickerIcon"
@ -37,4 +49,4 @@
android:scaleType="fitCenter"/>
</RelativeLayout>
</FrameLayout>
</RelativeLayout>

View File

@ -73,6 +73,7 @@
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/element_spacing_small"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
tools:text="@string/sample_status_text"/>
@ -81,7 +82,6 @@
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/element_spacing_small"
android:textColor="?android:attr/textColorTertiary"
tools:text="12:00"/>
</LinearLayout>