From 4a36a4b857f910b1672327b6662a6cfcfc92f619 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Tue, 18 Apr 2017 23:10:44 +0800 Subject: [PATCH] finished login flow for Mastodon #712 added account framework support for Mastodon #712 --- .../twidere/model/util/AccountUtils.java | 4 +- .../twidere/activity/SignInActivity.kt | 209 +++++++++--------- .../extension/model/AccountExtensions.kt | 18 +- .../model/api/mastodon/AccountExtensions.kt | 53 +++++ .../twidere/loader/ParcelableUserLoader.kt | 50 +++-- .../twidere/util/ContentValuesCreator.kt | 7 - .../ic_account_logo_mastodon-mdpi.svg | 21 ++ 7 files changed, 221 insertions(+), 141 deletions(-) create mode 100644 twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/api/mastodon/AccountExtensions.kt create mode 100644 twidere/src/main/svg/drawable/ic_account_logo_mastodon-mdpi.svg diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java b/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java index e72685028..9feef6b43 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java @@ -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; } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt index 00edacbae..df07d14fc 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SignInActivity.kt @@ -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(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>() { - protected val activityRef = WeakReference(activity) - - protected val profileImageSize: String = activity.getString(R.string.profile_image_size) - - override final fun doInBackground(vararg args: Any?): SingleResponse { - try { - return SingleResponse.getInstance(performLogin()) - } catch (e: Exception) { - return SingleResponse.getInstance(e) - } - } - - abstract fun performLogin(): SignInResponse - - override fun onPostExecute(result: SingleResponse) { - 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>() { + protected val activityRef = WeakReference(activity) + + protected val profileImageSize: String = activity.getString(R.string.profile_image_size) + + override final fun doInBackground(vararg args: Any?): SingleResponse { + try { + return SingleResponse.getInstance(performLogin()) + } catch (e: Exception) { + return SingleResponse.getInstance(e) + } + } + + abstract fun performLogin(): SignInResponse + + override fun onPostExecute(result: SingleResponse) { + 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 + 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) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountExtensions.kt index 5a0897608..129000a8a 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountExtensions.kt @@ -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 { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/api/mastodon/AccountExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/api/mastodon/AccountExtensions.kt new file mode 100644 index 000000000..a72c86381 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/api/mastodon/AccountExtensions.kt @@ -0,0 +1,53 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * 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 . + */ + +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 \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/loader/ParcelableUserLoader.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/loader/ParcelableUserLoader.kt index cf0830f17..a15e26bb3 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/loader/ParcelableUserLoader.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/loader/ParcelableUserLoader.kt @@ -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 @@ -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(EXTRA_USER) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentValuesCreator.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentValuesCreator.kt index 601197878..c07038656 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentValuesCreator.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/ContentValuesCreator.kt @@ -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()) diff --git a/twidere/src/main/svg/drawable/ic_account_logo_mastodon-mdpi.svg b/twidere/src/main/svg/drawable/ic_account_logo_mastodon-mdpi.svg new file mode 100644 index 000000000..64d564ae3 --- /dev/null +++ b/twidere/src/main/svg/drawable/ic_account_logo_mastodon-mdpi.svg @@ -0,0 +1,21 @@ + + + + ic_account_logo_mastodon-mdpi + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file