finished login flow for Mastodon #712
added account framework support for Mastodon #712
This commit is contained in:
parent
2e2321130f
commit
4a36a4b857
|
@ -148,7 +148,9 @@ public class AccountUtils {
|
|||
case AccountType.STATUSNET: {
|
||||
return R.drawable.ic_account_logo_statusnet;
|
||||
}
|
||||
|
||||
case AccountType.MASTODON: {
|
||||
return R.drawable.ic_account_logo_mastodon;
|
||||
}
|
||||
}
|
||||
return R.drawable.ic_account_logo_twitter;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.mariotaku.microblog.library.twitter.model.Paging
|
|||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.restfu.http.Endpoint
|
||||
import org.mariotaku.restfu.oauth.OAuthToken
|
||||
import org.mariotaku.restfu.oauth2.OAuth2Authorization
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
|
@ -74,6 +75,7 @@ import org.mariotaku.twidere.constant.defaultAPIConfigKey
|
|||
import org.mariotaku.twidere.constant.randomizeAccountNameKey
|
||||
import org.mariotaku.twidere.extension.applyTheme
|
||||
import org.mariotaku.twidere.extension.getNonEmptyString
|
||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.getColor
|
||||
import org.mariotaku.twidere.extension.model.getOAuthAuthorization
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
|
@ -89,10 +91,7 @@ import org.mariotaku.twidere.model.UserKey
|
|||
import org.mariotaku.twidere.model.account.AccountExtras
|
||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
||||
import org.mariotaku.twidere.model.account.cred.BasicCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.Credentials
|
||||
import org.mariotaku.twidere.model.account.cred.EmptyCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.OAuthCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.*
|
||||
import org.mariotaku.twidere.model.analyzer.SignIn
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||
|
@ -344,7 +343,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
private fun performMastodonLogin() {
|
||||
val weakThis = WeakReference(this)
|
||||
val host = editUsername.string?.takeIf(String::isNotEmpty) ?: run {
|
||||
Toast.makeText(this, R.string.message_toast_invalid_mastodon_username,
|
||||
Toast.makeText(this, R.string.message_toast_invalid_mastodon_host,
|
||||
Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
@ -397,30 +396,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
AsyncTaskUtils.executeTask<AbstractSignInTask, Any>(signInTask)
|
||||
}
|
||||
|
||||
private fun finishMastodonBrowserLogin(host: String, clientId: String, clientSecret: String,
|
||||
code: String) {
|
||||
val weakThis = WeakReference(this)
|
||||
executeAfterFragmentResumed { activity ->
|
||||
ProgressDialogFragment.show(activity.supportFragmentManager, "open_browser_auth")
|
||||
} and task {
|
||||
val activity = weakThis.get() ?: throw InterruptedException()
|
||||
val endpoint = Endpoint("https://$host/")
|
||||
val oauth2 = newMicroBlogInstance(activity, endpoint, EmptyAuthorization(),
|
||||
AccountType.MASTODON, MastodonOAuth2::class.java)
|
||||
return@task oauth2.getToken(clientId, clientSecret, code, MASTODON_CALLBACK_URL)
|
||||
}.successUi { token ->
|
||||
DebugLog.d(msg = "$token")
|
||||
}.failUi {
|
||||
val activity = weakThis.get() ?: return@failUi
|
||||
// TODO show error message
|
||||
}.alwaysUi {
|
||||
executeAfterFragmentResumed {
|
||||
it.supportFragmentManager.dismissDialogFragment("open_browser_auth")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onSignInResult(result: SignInResponse) {
|
||||
private fun onSignInResult(result: SignInResponse) {
|
||||
val am = AccountManager.get(this)
|
||||
setSignInButton()
|
||||
if (result.alreadyLoggedIn) {
|
||||
|
@ -429,14 +405,14 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
Toast.makeText(this, R.string.message_toast_already_logged_in, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
result.addAccount(am, preferences[randomizeAccountNameKey])
|
||||
val (type, extras) = result.typeExtras
|
||||
Analyzer.log(SignIn(true, accountType = type, credentialsType = apiConfig.credentialsType,
|
||||
officialKey = extras?.official ?: false))
|
||||
Analyzer.log(SignIn(true, accountType = result.type,
|
||||
credentialsType = apiConfig.credentialsType,
|
||||
officialKey = result.extras?.official ?: false))
|
||||
finishSignIn()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun dismissDialogFragment(tag: String) {
|
||||
private fun dismissDialogFragment(tag: String) {
|
||||
executeAfterFragmentResumed {
|
||||
val fm = supportFragmentManager
|
||||
val f = fm.findFragmentByTag(tag)
|
||||
|
@ -526,6 +502,12 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private fun finishMastodonBrowserLogin(host: String, clientId: String, clientSecret: String, code: String) {
|
||||
signInTask = MastodonLoginTask(this, host, clientId, clientSecret, code)
|
||||
AsyncTaskUtils.executeTask(signInTask)
|
||||
}
|
||||
|
||||
private fun handleBrowserLoginResult(intent: Intent?) {
|
||||
if (intent == null) return
|
||||
val verifier = intent.getStringExtra(EXTRA_OAUTH_VERIFIER)
|
||||
|
@ -862,62 +844,13 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
}
|
||||
}
|
||||
|
||||
internal abstract class AbstractSignInTask(activity: SignInActivity) : AsyncTask<Any, Runnable, SingleResponse<SignInResponse>>() {
|
||||
protected val activityRef = WeakReference(activity)
|
||||
|
||||
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
||||
|
||||
override final fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
||||
try {
|
||||
return SingleResponse.getInstance(performLogin())
|
||||
} catch (e: Exception) {
|
||||
return SingleResponse.getInstance(e)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun performLogin(): SignInResponse
|
||||
|
||||
override fun onPostExecute(result: SingleResponse<SignInResponse>) {
|
||||
val activity = activityRef.get()
|
||||
activity?.dismissDialogFragment(FRAGMENT_TAG_SIGN_IN_PROGRESS)
|
||||
if (result.hasData()) {
|
||||
activity?.onSignInResult(result.data!!)
|
||||
} else {
|
||||
activity?.onSignInError(result.exception!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreExecute() {
|
||||
val activity = activityRef.get()
|
||||
activity?.onSignInStart()
|
||||
}
|
||||
|
||||
override fun onProgressUpdate(vararg values: Runnable) {
|
||||
for (value in values) {
|
||||
value.run()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(MicroBlogException::class)
|
||||
internal fun analyseUserProfileColor(user: User?): Int {
|
||||
if (user == null) throw MicroBlogException("Unable to get user info")
|
||||
return ParcelableUserUtils.parseColor(user.profileLinkColor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class BrowserSignInTask(context: SignInActivity, private val apiConfig: CustomAPIConfig,
|
||||
internal class BrowserSignInTask(activity: SignInActivity, private val apiConfig: CustomAPIConfig,
|
||||
private val requestToken: OAuthToken, private val oauthVerifier: String?) :
|
||||
AbstractSignInTask(context) {
|
||||
|
||||
private val context: Context
|
||||
|
||||
init {
|
||||
this.context = context
|
||||
}
|
||||
AbstractSignInTask(activity) {
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun performLogin(): SignInResponse {
|
||||
val context = activityRef.get() ?: throw InterruptedException()
|
||||
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
||||
val apiUrlFormat = apiConfig.apiUrlFormat ?: throw MicroBlogException("No API URL format")
|
||||
var auth = apiConfig.getOAuthAuthorization() ?:
|
||||
|
@ -941,10 +874,10 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val typeExtras = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val userId = apiUser.id
|
||||
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, typeExtras.first,
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, type,
|
||||
profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(context)
|
||||
val account = AccountUtils.findByAccountKey(am, accountKey)
|
||||
|
@ -963,11 +896,42 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
credentials.access_token_secret = accessToken.oauthTokenSecret
|
||||
|
||||
return SignInResponse(account != null, Credentials.Type.OAUTH, credentials, user, color,
|
||||
typeExtras)
|
||||
type, extras)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class MastodonLoginTask(context: SignInActivity, val host: String, val clientId: String,
|
||||
val clientSecret: String, val code: String) : AbstractSignInTask(context) {
|
||||
@Throws(Exception::class)
|
||||
override fun performLogin(): SignInResponse {
|
||||
val context = activityRef.get() ?: throw InterruptedException()
|
||||
val oauth2 = newMicroBlogInstance(context, Endpoint("https://$host/"),
|
||||
EmptyAuthorization(), AccountType.MASTODON, MastodonOAuth2::class.java)
|
||||
val token = oauth2.getToken(clientId, clientSecret, code, MASTODON_CALLBACK_URL)
|
||||
|
||||
val endpoint = Endpoint("https://$host/api/")
|
||||
val auth = OAuth2Authorization(token.accessToken)
|
||||
val mastodon = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
||||
accountType = AccountType.MASTODON, cls = Mastodon::class.java)
|
||||
val apiAccount = mastodon.verifyCredentials()
|
||||
var color = 0
|
||||
val accountKey = UserKey(apiAccount.id, host)
|
||||
val user = apiAccount.toParcelable(accountKey)
|
||||
val am = AccountManager.get(context)
|
||||
val account = AccountUtils.findByAccountKey(am, accountKey)
|
||||
if (account != null) {
|
||||
color = account.getColor(am)
|
||||
}
|
||||
val credentials = OAuth2Credentials()
|
||||
credentials.api_url_format = endpoint.url
|
||||
credentials.no_version_suffix = true
|
||||
|
||||
credentials.access_token = token.accessToken
|
||||
return SignInResponse(account != null, Credentials.Type.OAUTH2, credentials, user,
|
||||
color, AccountType.MASTODON, null)
|
||||
}
|
||||
}
|
||||
|
||||
internal class SignInTask(
|
||||
activity: SignInActivity,
|
||||
|
@ -1052,9 +1016,9 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
|
||||
val userId = apiUser.id!!
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val typeExtras = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, typeExtras.first,
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, type,
|
||||
profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
val account = AccountUtils.findByAccountKey(am, accountKey)
|
||||
|
@ -1067,7 +1031,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
credentials.username = username
|
||||
credentials.password = password
|
||||
return SignInResponse(account != null, Credentials.Type.BASIC, credentials, user,
|
||||
color, typeExtras)
|
||||
color, type, extras)
|
||||
}
|
||||
|
||||
|
||||
|
@ -1083,9 +1047,9 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
val apiUser = twitter.verifyCredentials()
|
||||
val userId = apiUser.id!!
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val typeExtras = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, typeExtras.first,
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, type,
|
||||
profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
val account = AccountUtils.findByAccountKey(am, accountKey)
|
||||
|
@ -1097,7 +1061,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
credentials.no_version_suffix = apiConfig.isNoVersionSuffix
|
||||
|
||||
return SignInResponse(account != null, Credentials.Type.EMPTY, credentials, user, color,
|
||||
typeExtras)
|
||||
type, extras)
|
||||
}
|
||||
|
||||
@Throws(MicroBlogException::class)
|
||||
|
@ -1111,9 +1075,9 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
accountType = apiConfig.type, cls = MicroBlog::class.java)
|
||||
val apiUser = twitter.verifyCredentials()
|
||||
var color = analyseUserProfileColor(apiUser)
|
||||
val typeExtras = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val (type, extras) = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
||||
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, typeExtras.first,
|
||||
val user = ParcelableUserUtils.fromUser(apiUser, accountKey, type,
|
||||
profileImageSize = profileImageSize)
|
||||
val am = AccountManager.get(activity)
|
||||
val account = AccountUtils.findByAccountKey(am, accountKey)
|
||||
|
@ -1131,7 +1095,7 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
credentials.access_token = accessToken.oauthToken
|
||||
credentials.access_token_secret = accessToken.oauthTokenSecret
|
||||
|
||||
return SignInResponse(account != null, authType, credentials, user, color, typeExtras)
|
||||
return SignInResponse(account != null, authType, credentials, user, color, type, extras)
|
||||
}
|
||||
|
||||
internal class WrongBasicCredentialException : OAuthPasswordAuthenticator.AuthenticationException()
|
||||
|
@ -1186,25 +1150,70 @@ class SignInActivity : BaseActivity(), OnClickListener, TextWatcher,
|
|||
|
||||
}
|
||||
|
||||
internal abstract class AbstractSignInTask(activity: SignInActivity) : AsyncTask<Any, Runnable, SingleResponse<SignInResponse>>() {
|
||||
protected val activityRef = WeakReference(activity)
|
||||
|
||||
protected val profileImageSize: String = activity.getString(R.string.profile_image_size)
|
||||
|
||||
override final fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
||||
try {
|
||||
return SingleResponse.getInstance(performLogin())
|
||||
} catch (e: Exception) {
|
||||
return SingleResponse.getInstance(e)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun performLogin(): SignInResponse
|
||||
|
||||
override fun onPostExecute(result: SingleResponse<SignInResponse>) {
|
||||
val activity = activityRef.get()
|
||||
activity?.dismissDialogFragment(FRAGMENT_TAG_SIGN_IN_PROGRESS)
|
||||
if (result.hasData()) {
|
||||
activity?.onSignInResult(result.data!!)
|
||||
} else {
|
||||
activity?.onSignInError(result.exception!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreExecute() {
|
||||
val activity = activityRef.get()
|
||||
activity?.onSignInStart()
|
||||
}
|
||||
|
||||
override fun onProgressUpdate(vararg values: Runnable) {
|
||||
for (value in values) {
|
||||
value.run()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(MicroBlogException::class)
|
||||
internal fun analyseUserProfileColor(user: User?): Int {
|
||||
if (user == null) throw MicroBlogException("Unable to get user info")
|
||||
return ParcelableUserUtils.parseColor(user.profileLinkColor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal data class SignInResponse(
|
||||
val alreadyLoggedIn: Boolean,
|
||||
@Credentials.Type val credsType: String = Credentials.Type.EMPTY,
|
||||
val credentials: Credentials,
|
||||
val user: ParcelableUser,
|
||||
val color: Int = 0,
|
||||
val typeExtras: Pair<String, AccountExtras?>
|
||||
val type: String,
|
||||
val extras: AccountExtras?
|
||||
) {
|
||||
|
||||
private fun writeAccountInfo(action: (k: String, v: String?) -> Unit) {
|
||||
action(ACCOUNT_USER_DATA_KEY, user.key.toString())
|
||||
action(ACCOUNT_USER_DATA_TYPE, typeExtras.first)
|
||||
action(ACCOUNT_USER_DATA_TYPE, type)
|
||||
action(ACCOUNT_USER_DATA_CREDS_TYPE, credsType)
|
||||
|
||||
action(ACCOUNT_USER_DATA_ACTIVATED, true.toString())
|
||||
action(ACCOUNT_USER_DATA_COLOR, toHexColor(color, format = HexColorFormat.RGB))
|
||||
|
||||
action(ACCOUNT_USER_DATA_USER, JsonSerializer.serialize(user))
|
||||
action(ACCOUNT_USER_DATA_EXTRAS, typeExtras.second?.let { JsonSerializer.serialize(it) })
|
||||
action(ACCOUNT_USER_DATA_EXTRAS, extras?.let { JsonSerializer.serialize(it) })
|
||||
}
|
||||
|
||||
private fun writeAuthToken(am: AccountManager, account: Account) {
|
||||
|
|
|
@ -17,10 +17,7 @@ import org.mariotaku.twidere.model.UserKey
|
|||
import org.mariotaku.twidere.model.account.AccountExtras
|
||||
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
||||
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
||||
import org.mariotaku.twidere.model.account.cred.BasicCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.Credentials
|
||||
import org.mariotaku.twidere.model.account.cred.EmptyCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.OAuthCredentials
|
||||
import org.mariotaku.twidere.model.account.cred.*
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.model.util.AccountUtils.ACCOUNT_USER_DATA_KEYS
|
||||
import org.mariotaku.twidere.util.JsonSerializer
|
||||
|
@ -165,13 +162,12 @@ private fun AccountManager.getNonNullUserData(account: Account, key: String): St
|
|||
}
|
||||
}
|
||||
|
||||
private fun parseCredentials(authToken: String, @Credentials.Type authType: String): Credentials {
|
||||
when (authType) {
|
||||
Credentials.Type.OAUTH, Credentials.Type.XAUTH -> return JsonSerializer.parse(authToken, OAuthCredentials::class.java)
|
||||
Credentials.Type.BASIC -> return JsonSerializer.parse(authToken, BasicCredentials::class.java)
|
||||
Credentials.Type.EMPTY -> return JsonSerializer.parse(authToken, EmptyCredentials::class.java)
|
||||
}
|
||||
throw UnsupportedOperationException()
|
||||
private fun parseCredentials(authToken: String, @Credentials.Type authType: String) = when (authType) {
|
||||
Credentials.Type.OAUTH, Credentials.Type.XAUTH -> JsonSerializer.parse(authToken, OAuthCredentials::class.java)
|
||||
Credentials.Type.BASIC -> JsonSerializer.parse(authToken, BasicCredentials::class.java)
|
||||
Credentials.Type.EMPTY -> JsonSerializer.parse(authToken, EmptyCredentials::class.java)
|
||||
Credentials.Type.OAUTH2 -> JsonSerializer.parse(authToken, OAuth2Credentials::class.java)
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
internal object AccountDataQueue {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.extension.model.api.mastodon
|
||||
|
||||
import org.mariotaku.microblog.library.mastodon.model.Account
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/4/18.
|
||||
*/
|
||||
|
||||
fun Account.toParcelable(accountKey: UserKey, position: Long = 0): ParcelableUser {
|
||||
val obj = ParcelableUser()
|
||||
obj.position = position
|
||||
obj.account_key = accountKey
|
||||
obj.key = UserKey(id, host ?: accountKey.host)
|
||||
obj.created_at = createdAt?.time ?: -1
|
||||
obj.is_protected = isLocked
|
||||
obj.name = displayName
|
||||
obj.screen_name = username
|
||||
obj.description_plain = note
|
||||
obj.description_unescaped = note
|
||||
obj.url = url
|
||||
obj.profile_image_url = avatar
|
||||
obj.profile_banner_url = header
|
||||
obj.followers_count = followersCount
|
||||
obj.friends_count = followingCount
|
||||
obj.statuses_count = statusesCount
|
||||
obj.favorites_count = -1
|
||||
obj.listed_count = -1
|
||||
obj.media_count = -1
|
||||
return obj
|
||||
}
|
||||
|
||||
val Account.host: String? get() = acct?.let(UserKey::valueOf)?.host
|
|
@ -30,13 +30,14 @@ import org.mariotaku.ktextension.set
|
|||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||
import org.mariotaku.sqliteqb.library.Columns
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.annotation.Referral
|
||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
|
@ -47,7 +48,6 @@ import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
|||
import org.mariotaku.twidere.model.util.UserKeyUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
|
||||
import org.mariotaku.twidere.task.UpdateAccountInfoTask
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator
|
||||
import org.mariotaku.twidere.util.TwitterWrapper
|
||||
import org.mariotaku.twidere.util.UserColorNameManager
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponent
|
||||
|
@ -96,7 +96,6 @@ class ParcelableUserLoader(
|
|||
}
|
||||
}
|
||||
}
|
||||
val twitter = details.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
||||
if (loadFromCache) {
|
||||
val where: Expression
|
||||
val whereArgs: Array<String>
|
||||
|
@ -139,27 +138,13 @@ class ParcelableUserLoader(
|
|||
}
|
||||
}
|
||||
try {
|
||||
val twitterUser: User
|
||||
if (extras != null && Referral.SELF_PROFILE == extras.getString(EXTRA_REFERRAL)) {
|
||||
twitterUser = twitter.verifyCredentials()
|
||||
} else {
|
||||
var profileUrl: String? = null
|
||||
if (extras != null) {
|
||||
profileUrl = extras.getString(EXTRA_PROFILE_URL)
|
||||
}
|
||||
if (details.type == AccountType.STATUSNET && userKey != null && profileUrl != null
|
||||
&& details.key.host != userKey.host) {
|
||||
twitterUser = twitter.showExternalProfile(profileUrl)
|
||||
} else {
|
||||
val id = userKey?.id
|
||||
twitterUser = TwitterWrapper.tryShowUser(twitter, id, screenName, details.type)
|
||||
}
|
||||
val user = when (details.type) {
|
||||
AccountType.MASTODON -> showMastodonUser(details)
|
||||
else -> showMicroBlogUser(details)
|
||||
}
|
||||
val cachedUserValues = ContentValuesCreator.createCachedUser(twitterUser, details.type,
|
||||
profileImageSize)
|
||||
val creator = ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java)
|
||||
val cachedUserValues = creator.create(user)
|
||||
resolver.insert(CachedUsers.CONTENT_URI, cachedUserValues)
|
||||
val user = ParcelableUserUtils.fromUser(twitterUser, accountKey, details.type,
|
||||
profileImageSize = profileImageSize)
|
||||
ParcelableUserUtils.updateExtraInformation(user, details, userColorNameManager)
|
||||
return SingleResponse(user).apply {
|
||||
extras[EXTRA_ACCOUNT] = details
|
||||
|
@ -171,6 +156,27 @@ class ParcelableUserLoader(
|
|||
|
||||
}
|
||||
|
||||
private fun showMastodonUser(details: AccountDetails): ParcelableUser {
|
||||
val mastodon = details.newMicroBlogInstance(context, Mastodon::class.java)
|
||||
if (userKey != null) return mastodon.getAccount(userKey.id).toParcelable(details.key)
|
||||
throw MicroBlogException("No user id")
|
||||
}
|
||||
|
||||
private fun showMicroBlogUser(details: AccountDetails): ParcelableUser {
|
||||
val microBlog = details.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||
val profileUrl = extras?.getString(EXTRA_PROFILE_URL)
|
||||
val response = if (extras != null && Referral.SELF_PROFILE == extras.getString(EXTRA_REFERRAL)) {
|
||||
microBlog.verifyCredentials()
|
||||
} else if (details.type == AccountType.STATUSNET && userKey != null && profileUrl != null
|
||||
&& details.key.host != userKey.host) {
|
||||
microBlog.showExternalProfile(profileUrl)
|
||||
} else {
|
||||
TwitterWrapper.tryShowUser(microBlog, userKey?.id, screenName, details.type)
|
||||
}
|
||||
return ParcelableUserUtils.fromUser(response, details.key, details.type,
|
||||
profileImageSize = profileImageSize)
|
||||
}
|
||||
|
||||
override fun onStartLoading() {
|
||||
if (!omitIntentExtra && extras != null) {
|
||||
val user = extras.getParcelable<ParcelableUser>(EXTRA_USER)
|
||||
|
|
|
@ -24,21 +24,14 @@ import org.mariotaku.ktextension.mapToArray
|
|||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.microblog.library.twitter.model.SavedSearch
|
||||
import org.mariotaku.microblog.library.twitter.model.Status
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||
import org.mariotaku.twidere.model.util.getActivityStatus
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches
|
||||
|
||||
object ContentValuesCreator {
|
||||
|
||||
fun createCachedUser(user: User, accountType: String, profileImageSize: String = "normal"): ContentValues {
|
||||
return ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java)
|
||||
.create(ParcelableUserUtils.fromUser(user, accountType, profileImageSize = profileImageSize))
|
||||
}
|
||||
|
||||
fun createFilteredUser(status: ParcelableStatus): ContentValues {
|
||||
val values = ContentValues()
|
||||
values.put(Filters.Users.USER_KEY, status.user_key.toString())
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 43.1 (39012) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>ic_account_logo_mastodon-mdpi</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<circle id="path-1" cx="24" cy="24" r="24"></circle>
|
||||
</defs>
|
||||
<g id="Miscellaneous" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="ic_account_logo_mastodon-mdpi">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<use id="Oval-2" fill="#FAFAFA" xlink:href="#path-1"></use>
|
||||
<rect id="Rectangle" fill="#FFFFFF" mask="url(#mask-2)" x="0" y="0" width="48" height="48"></rect>
|
||||
<path d="M23.878481,13.0025316 L29.043038,13.0025316 C28.0405063,13.7012658 27.7063291,15.7367089 27.7063291,16.8 L27.7063291,26.521519 C27.7063291,28.6481013 26.035443,30.2886076 23.878481,30.2886076 C21.7518987,30.2886076 20.0506329,28.6177215 20.0506329,26.4911392 L20.0506329,16.7696203 C20.0506329,14.7037975 21.721519,13.0025316 23.878481,13.0025316 L23.878481,13.0025316 Z" id="Path" fill="#1BB4FE" mask="url(#mask-2)"></path>
|
||||
<path d="M10.6329114,15.3721519 C12.7594937,15.3721519 14.4607595,17.043038 14.4607595,19.1392405 L14.4607595,28.8607595 C14.4607595,29.8936709 14.764557,31.9594937 15.7670886,32.6278481 L10.6329114,32.6278481 C8.50632911,32.6278481 6.80506329,30.956962 6.80506329,28.8607595 L6.80506329,19.1392405 C6.80506329,17.0126582 8.47594937,15.3721519 10.6329114,15.3721519 Z" id="Path" fill="#1BB4FE" mask="url(#mask-2)"></path>
|
||||
<path d="M37.0632911,15.3721519 C39.1898734,15.3721519 40.8911392,17.043038 40.8911392,19.1392405 L40.8911392,28.8607595 C40.8911392,30.9873418 39.1898734,32.6278481 37.0329114,32.6278481 L31.8683544,32.6278481 C32.8405063,31.9594937 33.1746835,29.8936709 33.1746835,28.8607595 L33.1746835,19.1392405 C33.1746835,17.0126582 34.8759494,15.3721519 37.0025316,15.3721519 L37.0632911,15.3721519 Z" id="Path" fill="#1BB4FE" mask="url(#mask-2)"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
Loading…
Reference in New Issue