2018-06-18 13:26:18 +02:00
|
|
|
/* Copyright 2018 Conny Duck
|
|
|
|
*
|
|
|
|
* This file is a part of Tusky.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Tusky 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 Tusky; if not,
|
|
|
|
* see <http://www.gnu.org/licenses>. */
|
|
|
|
|
|
|
|
package com.keylesspalace.tusky
|
|
|
|
|
|
|
|
import android.animation.ArgbEvaluator
|
|
|
|
import android.arch.lifecycle.Observer
|
|
|
|
import android.arch.lifecycle.ViewModelProviders
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.Intent
|
|
|
|
import android.graphics.Color
|
|
|
|
import android.graphics.PorterDuff
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.preference.PreferenceManager
|
|
|
|
import android.support.annotation.AttrRes
|
|
|
|
import android.support.annotation.ColorInt
|
|
|
|
import android.support.annotation.Px
|
|
|
|
import android.support.design.widget.*
|
|
|
|
import android.support.text.emoji.EmojiCompat
|
2018-07-30 15:42:45 +02:00
|
|
|
import android.support.v4.app.ActivityOptionsCompat
|
2018-06-18 13:26:18 +02:00
|
|
|
import android.support.v4.app.Fragment
|
|
|
|
import android.support.v4.content.ContextCompat
|
|
|
|
import android.support.v4.view.ViewCompat
|
|
|
|
import android.support.v4.widget.TextViewCompat
|
2018-09-29 19:44:50 +02:00
|
|
|
import android.support.v7.app.AlertDialog
|
2018-06-18 13:26:18 +02:00
|
|
|
import android.support.v7.widget.LinearLayoutManager
|
|
|
|
import android.view.Menu
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import com.keylesspalace.tusky.adapter.AccountFieldAdapter
|
|
|
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
|
|
|
import com.keylesspalace.tusky.entity.Account
|
|
|
|
import com.keylesspalace.tusky.entity.Relationship
|
|
|
|
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
|
|
|
import com.keylesspalace.tusky.interfaces.LinkListener
|
|
|
|
import com.keylesspalace.tusky.pager.AccountPagerAdapter
|
|
|
|
import com.keylesspalace.tusky.util.*
|
|
|
|
import com.keylesspalace.tusky.viewmodel.AccountViewModel
|
|
|
|
import com.squareup.picasso.Picasso
|
|
|
|
import dagger.android.AndroidInjector
|
|
|
|
import dagger.android.DispatchingAndroidInjector
|
|
|
|
import dagger.android.support.HasSupportFragmentInjector
|
|
|
|
import kotlinx.android.synthetic.main.activity_account.*
|
|
|
|
import kotlinx.android.synthetic.main.view_account_moved.*
|
|
|
|
import java.text.NumberFormat
|
|
|
|
import javax.inject.Inject
|
|
|
|
|
|
|
|
class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportFragmentInjector, LinkListener {
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
|
|
|
|
@Inject
|
|
|
|
lateinit var viewModelFactory: ViewModelFactory
|
|
|
|
|
|
|
|
private lateinit var viewModel: AccountViewModel
|
|
|
|
|
|
|
|
private val accountFieldAdapter = AccountFieldAdapter(this)
|
|
|
|
|
|
|
|
private lateinit var accountId: String
|
2018-07-05 21:14:32 +02:00
|
|
|
private var followState: FollowState = FollowState.NOT_FOLLOWING
|
2018-06-18 13:26:18 +02:00
|
|
|
private var blocking: Boolean = false
|
|
|
|
private var muting: Boolean = false
|
|
|
|
private var showingReblogs: Boolean = false
|
|
|
|
private var isSelf: Boolean = false
|
|
|
|
private var loadedAccount: Account? = null
|
|
|
|
|
|
|
|
// fields for scroll animation
|
|
|
|
private var hideFab: Boolean = false
|
|
|
|
private var oldOffset: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var toolbarColor: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var backgroundColor: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var statusBarColorTransparent: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var statusBarColorOpaque: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var textColorPrimary: Int = 0
|
|
|
|
@ColorInt
|
|
|
|
private var textColorSecondary: Int = 0
|
|
|
|
@Px
|
|
|
|
private var avatarSize: Float = 0f
|
|
|
|
@Px
|
|
|
|
private var titleVisibleHeight: Int = 0
|
|
|
|
|
|
|
|
private enum class FollowState {
|
|
|
|
NOT_FOLLOWING,
|
|
|
|
FOLLOWING,
|
|
|
|
REQUESTED
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
|
|
|
|
viewModel = ViewModelProviders.of(this, viewModelFactory)[AccountViewModel::class.java]
|
|
|
|
|
|
|
|
viewModel.accountData.observe(this, Observer<Resource<Account>> {
|
|
|
|
when (it) {
|
|
|
|
is Success -> onAccountChanged(it.data)
|
|
|
|
is Error -> {
|
|
|
|
Snackbar.make(accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
|
|
.setAction(R.string.action_retry) { reload() }
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
viewModel.relationshipData.observe(this, Observer<Resource<Relationship>> {
|
|
|
|
val relation = it?.data
|
|
|
|
if (relation != null) {
|
|
|
|
onRelationshipChanged(relation)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (it is Error) {
|
|
|
|
Snackbar.make(accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
|
|
|
.setAction(R.string.action_retry) { reload() }
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
val decorView = window.decorView
|
|
|
|
decorView.systemUiVisibility = decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
2018-09-16 18:54:12 +02:00
|
|
|
window.statusBarColor = Color.TRANSPARENT
|
2018-06-18 13:26:18 +02:00
|
|
|
|
|
|
|
setContentView(R.layout.activity_account)
|
|
|
|
|
|
|
|
val intent = intent
|
|
|
|
accountId = intent.getStringExtra(KEY_ACCOUNT_ID)
|
|
|
|
|
|
|
|
// set toolbar top margin according to system window insets
|
|
|
|
ViewCompat.setOnApplyWindowInsetsListener(accountCoordinatorLayout) { _, insets ->
|
|
|
|
val top = insets.systemWindowInsetTop
|
|
|
|
|
|
|
|
val toolbarParams = accountToolbar.layoutParams as CollapsingToolbarLayout.LayoutParams
|
|
|
|
toolbarParams.topMargin = top
|
|
|
|
|
|
|
|
insets.consumeSystemWindowInsets()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the toolbar.
|
|
|
|
setSupportActionBar(accountToolbar)
|
|
|
|
supportActionBar?.title = null
|
|
|
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
|
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
|
|
|
|
|
|
|
hideFab = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("fabHide", false)
|
|
|
|
|
|
|
|
toolbarColor = ThemeUtils.getColor(this, R.attr.toolbar_background_color)
|
|
|
|
backgroundColor = ThemeUtils.getColor(this, android.R.attr.colorBackground)
|
|
|
|
statusBarColorTransparent = ContextCompat.getColor(this, R.color.header_background_filter)
|
|
|
|
statusBarColorOpaque = ThemeUtils.getColor(this, R.attr.colorPrimaryDark)
|
|
|
|
textColorPrimary = ThemeUtils.getColor(this, android.R.attr.textColorPrimary)
|
|
|
|
textColorSecondary = ThemeUtils.getColor(this, android.R.attr.textColorSecondary)
|
|
|
|
avatarSize = resources.getDimensionPixelSize(R.dimen.account_activity_avatar_size).toFloat()
|
|
|
|
titleVisibleHeight = resources.getDimensionPixelSize(R.dimen.account_activity_scroll_title_visible_height)
|
|
|
|
|
|
|
|
ThemeUtils.setDrawableTint(this, accountToolbar.navigationIcon, R.attr.account_toolbar_icon_tint_uncollapsed)
|
|
|
|
ThemeUtils.setDrawableTint(this, accountToolbar.overflowIcon, R.attr.account_toolbar_icon_tint_uncollapsed)
|
|
|
|
|
|
|
|
// Add a listener to change the toolbar icon color when it enters/exits its collapsed state.
|
|
|
|
accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
|
|
|
|
@AttrRes var priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed
|
|
|
|
|
|
|
|
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
|
|
|
|
|
|
|
|
@AttrRes val attribute = if (titleVisibleHeight + verticalOffset < 0) {
|
|
|
|
accountToolbar.setTitleTextColor(textColorPrimary)
|
|
|
|
accountToolbar.setSubtitleTextColor(textColorSecondary)
|
|
|
|
|
|
|
|
R.attr.account_toolbar_icon_tint_collapsed
|
|
|
|
} else {
|
|
|
|
accountToolbar.setTitleTextColor(Color.TRANSPARENT)
|
|
|
|
accountToolbar.setSubtitleTextColor(Color.TRANSPARENT)
|
|
|
|
|
|
|
|
R.attr.account_toolbar_icon_tint_uncollapsed
|
|
|
|
}
|
|
|
|
if (attribute != priorAttribute) {
|
|
|
|
priorAttribute = attribute
|
|
|
|
val context = accountToolbar.context
|
|
|
|
ThemeUtils.setDrawableTint(context, accountToolbar.navigationIcon, attribute)
|
|
|
|
ThemeUtils.setDrawableTint(context, accountToolbar.overflowIcon, attribute)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hideFab && !isSelf && !blocking) {
|
|
|
|
if (verticalOffset > oldOffset) {
|
|
|
|
accountFloatingActionButton.show()
|
|
|
|
}
|
|
|
|
if (verticalOffset < oldOffset) {
|
|
|
|
accountFloatingActionButton.hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
oldOffset = verticalOffset
|
|
|
|
|
|
|
|
val scaledAvatarSize = (avatarSize + verticalOffset) / avatarSize
|
|
|
|
|
|
|
|
accountAvatarImageView.scaleX = scaledAvatarSize
|
|
|
|
accountAvatarImageView.scaleY = scaledAvatarSize
|
|
|
|
|
|
|
|
accountAvatarImageView.visible(scaledAvatarSize > 0)
|
|
|
|
|
|
|
|
var transparencyPercent = Math.abs(verticalOffset) / titleVisibleHeight.toFloat()
|
|
|
|
if (transparencyPercent > 1) transparencyPercent = 1f
|
|
|
|
|
2018-09-16 18:54:12 +02:00
|
|
|
window.statusBarColor = argbEvaluator.evaluate(transparencyPercent, statusBarColorTransparent, statusBarColorOpaque) as Int
|
2018-06-18 13:26:18 +02:00
|
|
|
|
|
|
|
val evaluatedToolbarColor = argbEvaluator.evaluate(transparencyPercent, Color.TRANSPARENT, toolbarColor) as Int
|
|
|
|
val evaluatedTabBarColor = argbEvaluator.evaluate(transparencyPercent, backgroundColor, toolbarColor) as Int
|
|
|
|
accountToolbar.setBackgroundColor(evaluatedToolbarColor)
|
|
|
|
accountHeaderInfoContainer.setBackgroundColor(evaluatedTabBarColor)
|
|
|
|
accountTabLayout.setBackgroundColor(evaluatedTabBarColor)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Initialise the default UI states.
|
|
|
|
accountFloatingActionButton.hide()
|
|
|
|
accountFollowButton.hide()
|
|
|
|
accountFollowsYouTextView.hide()
|
|
|
|
|
|
|
|
// Obtain information to fill out the profile.
|
|
|
|
viewModel.obtainAccount(accountId)
|
|
|
|
|
|
|
|
val activeAccount = accountManager.activeAccount
|
|
|
|
|
|
|
|
if (accountId == activeAccount?.accountId) {
|
|
|
|
isSelf = true
|
|
|
|
updateButtons()
|
|
|
|
} else {
|
|
|
|
isSelf = false
|
|
|
|
viewModel.obtainRelationship(accountId)
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup the RecyclerView for the account fields
|
|
|
|
accountFieldList.isNestedScrollingEnabled = false
|
|
|
|
accountFieldList.layoutManager = LinearLayoutManager(this)
|
|
|
|
accountFieldList.adapter = accountFieldAdapter
|
|
|
|
|
|
|
|
// Setup the tabs and timeline pager.
|
|
|
|
val adapter = AccountPagerAdapter(supportFragmentManager, accountId)
|
|
|
|
val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_media))
|
|
|
|
adapter.setPageTitles(pageTitles)
|
|
|
|
accountFragmentViewPager.pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
|
|
|
|
val pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable,
|
|
|
|
R.drawable.tab_page_margin_dark)
|
|
|
|
accountFragmentViewPager.setPageMarginDrawable(pageMarginDrawable)
|
|
|
|
accountFragmentViewPager.adapter = adapter
|
|
|
|
accountFragmentViewPager.offscreenPageLimit = 2
|
|
|
|
accountTabLayout.setupWithViewPager(accountFragmentViewPager)
|
|
|
|
|
|
|
|
val accountListClickListener = { v: View ->
|
|
|
|
val type = when (v.id) {
|
|
|
|
R.id.accountFollowers-> AccountListActivity.Type.FOLLOWERS
|
|
|
|
R.id.accountFollowing -> AccountListActivity.Type.FOLLOWING
|
|
|
|
else -> throw AssertionError()
|
|
|
|
}
|
|
|
|
val accountListIntent = AccountListActivity.newIntent(this, type, accountId)
|
2018-07-31 21:25:25 +02:00
|
|
|
startActivityWithSlideInAnimation(accountListIntent)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
accountFollowers.setOnClickListener(accountListClickListener)
|
|
|
|
accountFollowing.setOnClickListener(accountListClickListener)
|
|
|
|
|
|
|
|
accountStatuses.setOnClickListener {
|
|
|
|
// Make nice ripple effect on tab
|
|
|
|
accountTabLayout.getTabAt(0)!!.select()
|
|
|
|
val poorTabView = (accountTabLayout.getChildAt(0) as ViewGroup).getChildAt(0)
|
|
|
|
poorTabView.isPressed = true
|
|
|
|
accountTabLayout.postDelayed({ poorTabView.isPressed = false }, 300)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onAccountChanged(account: Account?) {
|
|
|
|
if (account != null) {
|
|
|
|
loadedAccount = account
|
|
|
|
val usernameFormatted = getString(R.string.status_username_format, account.username)
|
|
|
|
accountUsernameTextView.text = usernameFormatted
|
|
|
|
accountDisplayNameTextView.text = CustomEmojiHelper.emojifyString(account.name, account.emojis, accountDisplayNameTextView)
|
|
|
|
if (supportActionBar != null) {
|
2018-07-14 21:36:47 +02:00
|
|
|
try {
|
|
|
|
supportActionBar?.title = EmojiCompat.get().process(account.name)
|
|
|
|
} catch (e: IllegalStateException) {
|
|
|
|
supportActionBar?.title = account.name
|
|
|
|
}
|
2018-06-18 13:26:18 +02:00
|
|
|
|
|
|
|
val subtitle = String.format(getString(R.string.status_username_format),
|
|
|
|
account.username)
|
|
|
|
supportActionBar?.subtitle = subtitle
|
|
|
|
}
|
|
|
|
val emojifiedNote = CustomEmojiHelper.emojifyText(account.note, account.emojis, accountNoteTextView)
|
|
|
|
LinkHelper.setClickableText(accountNoteTextView, emojifiedNote, null, this)
|
|
|
|
|
|
|
|
accountLockedImageView.visible(account.locked)
|
|
|
|
accountBadgeTextView.visible(account.bot)
|
|
|
|
|
|
|
|
Picasso.with(this)
|
|
|
|
.load(account.avatar)
|
|
|
|
.placeholder(R.drawable.avatar_default)
|
|
|
|
.into(accountAvatarImageView)
|
|
|
|
Picasso.with(this)
|
|
|
|
.load(account.header)
|
2018-08-24 23:07:54 +02:00
|
|
|
.fit() // prevents crash with large header images
|
|
|
|
.centerCrop()
|
2018-06-18 13:26:18 +02:00
|
|
|
.into(accountHeaderImageView)
|
|
|
|
|
2018-07-30 15:42:45 +02:00
|
|
|
accountAvatarImageView.setOnClickListener { avatarView ->
|
|
|
|
val intent = ViewMediaActivity.newAvatarIntent(avatarView.context, account.avatar)
|
|
|
|
|
|
|
|
ViewCompat.setTransitionName(avatarView, account.avatar)
|
|
|
|
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, avatarView, account.avatar)
|
|
|
|
|
|
|
|
startActivity(intent, options.toBundle())
|
|
|
|
}
|
|
|
|
|
2018-07-01 13:33:16 +02:00
|
|
|
accountFieldAdapter.fields = account.fields ?: emptyList()
|
|
|
|
accountFieldAdapter.emojis = account.emojis ?: emptyList()
|
2018-06-18 13:26:18 +02:00
|
|
|
accountFieldAdapter.notifyDataSetChanged()
|
|
|
|
|
|
|
|
if (account.moved != null) {
|
|
|
|
val movedAccount = account.moved
|
|
|
|
|
|
|
|
accountMovedView.show()
|
|
|
|
|
|
|
|
// necessary because accountMovedView is now replaced in layout hierachy
|
|
|
|
findViewById<View>(R.id.accountMovedView).setOnClickListener {
|
|
|
|
onViewAccount(movedAccount.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
accountMovedDisplayName.text = movedAccount.name
|
|
|
|
accountMovedUsername.text = getString(R.string.status_username_format, movedAccount.username)
|
|
|
|
|
|
|
|
Picasso.with(this)
|
|
|
|
.load(movedAccount.avatar)
|
|
|
|
.placeholder(R.drawable.avatar_default)
|
|
|
|
.into(accountMovedAvatar)
|
|
|
|
|
|
|
|
accountMovedText.text = getString(R.string.account_moved_description, movedAccount.displayName)
|
|
|
|
|
|
|
|
// this is necessary because API 19 can't handle vector compound drawables
|
|
|
|
val movedIcon = ContextCompat.getDrawable(this, R.drawable.ic_briefcase)?.mutate()
|
|
|
|
val textColor = ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
|
|
|
movedIcon?.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
|
|
|
|
|
|
|
|
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(accountMovedText, movedIcon, null, null, null)
|
|
|
|
|
|
|
|
accountFollowers.hide()
|
|
|
|
accountFollowing.hide()
|
|
|
|
accountStatuses.hide()
|
|
|
|
accountTabLayout.hide()
|
|
|
|
accountFragmentViewPager.hide()
|
|
|
|
}
|
|
|
|
|
2018-10-03 21:53:31 +02:00
|
|
|
if (account.isRemote()) {
|
|
|
|
accountRemoveView.show()
|
|
|
|
accountRemoveView.setOnClickListener {
|
|
|
|
LinkHelper.openLink(account.url, this)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-18 13:26:18 +02:00
|
|
|
val numberFormat = NumberFormat.getNumberInstance()
|
|
|
|
accountFollowersTextView.text = numberFormat.format(account.followersCount)
|
|
|
|
accountFollowingTextView.text = numberFormat.format(account.followingCount)
|
|
|
|
accountStatusesTextView.text = numberFormat.format(account.statusesCount)
|
|
|
|
|
2018-11-16 13:31:03 +01:00
|
|
|
accountFloatingActionButton.setOnClickListener { mention() }
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2018-11-16 13:31:03 +01:00
|
|
|
accountFollowButton.setOnClickListener {
|
2018-06-18 13:26:18 +02:00
|
|
|
if (isSelf) {
|
|
|
|
val intent = Intent(this@AccountActivity, EditProfileActivity::class.java)
|
2018-08-15 20:47:09 +02:00
|
|
|
startActivity(intent)
|
2018-06-18 13:26:18 +02:00
|
|
|
return@setOnClickListener
|
|
|
|
}
|
|
|
|
when (followState) {
|
|
|
|
AccountActivity.FollowState.NOT_FOLLOWING -> {
|
|
|
|
viewModel.changeFollowState(accountId)
|
|
|
|
}
|
|
|
|
AccountActivity.FollowState.REQUESTED -> {
|
|
|
|
showFollowRequestPendingDialog()
|
|
|
|
}
|
|
|
|
AccountActivity.FollowState.FOLLOWING -> {
|
|
|
|
showUnfollowWarningDialog()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
updateFollowButton()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
|
|
|
outState.putString(KEY_ACCOUNT_ID, accountId)
|
|
|
|
super.onSaveInstanceState(outState)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onRelationshipChanged(relation: Relationship) {
|
|
|
|
followState = when {
|
|
|
|
relation.following -> FollowState.FOLLOWING
|
|
|
|
relation.requested -> FollowState.REQUESTED
|
|
|
|
else -> FollowState.NOT_FOLLOWING
|
|
|
|
}
|
|
|
|
blocking = relation.blocking
|
|
|
|
muting = relation.muting
|
|
|
|
showingReblogs = relation.showingReblogs
|
|
|
|
|
|
|
|
accountFollowsYouTextView.visible(relation.followedBy)
|
|
|
|
|
|
|
|
updateButtons()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun reload() {
|
|
|
|
viewModel.obtainAccount(accountId, true)
|
|
|
|
viewModel.obtainRelationship(accountId)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun updateFollowButton() {
|
|
|
|
if(isSelf) {
|
|
|
|
accountFollowButton.setText(R.string.action_edit_own_profile)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
when (followState) {
|
|
|
|
AccountActivity.FollowState.NOT_FOLLOWING -> {
|
|
|
|
accountFollowButton.setText(R.string.action_follow)
|
|
|
|
}
|
|
|
|
AccountActivity.FollowState.REQUESTED -> {
|
|
|
|
accountFollowButton.setText(R.string.state_follow_requested)
|
|
|
|
}
|
|
|
|
AccountActivity.FollowState.FOLLOWING -> {
|
|
|
|
accountFollowButton.setText(R.string.action_unfollow)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun updateButtons() {
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
|
|
|
|
if (!blocking && loadedAccount?.moved == null) {
|
|
|
|
|
|
|
|
accountFollowButton.show()
|
|
|
|
updateFollowButton()
|
|
|
|
|
|
|
|
if(isSelf) {
|
|
|
|
accountFloatingActionButton.hide()
|
|
|
|
} else {
|
|
|
|
accountFloatingActionButton.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
accountFloatingActionButton.hide()
|
|
|
|
accountFollowButton.hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
|
|
menuInflater.inflate(R.menu.account_toolbar, menu)
|
|
|
|
return super.onCreateOptionsMenu(menu)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
|
|
|
if (!isSelf) {
|
|
|
|
val follow = menu.findItem(R.id.action_follow)
|
|
|
|
follow.title = if (followState == FollowState.NOT_FOLLOWING) {
|
|
|
|
getString(R.string.action_follow)
|
|
|
|
} else {
|
|
|
|
getString(R.string.action_unfollow)
|
|
|
|
}
|
|
|
|
|
|
|
|
follow.isVisible = followState != FollowState.REQUESTED
|
|
|
|
|
|
|
|
val block = menu.findItem(R.id.action_block)
|
|
|
|
block.title = if (blocking) {
|
|
|
|
getString(R.string.action_unblock)
|
|
|
|
} else {
|
|
|
|
getString(R.string.action_block)
|
|
|
|
}
|
|
|
|
|
|
|
|
val mute = menu.findItem(R.id.action_mute)
|
|
|
|
mute.title = if (muting) {
|
|
|
|
getString(R.string.action_unmute)
|
|
|
|
} else {
|
|
|
|
getString(R.string.action_mute)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (followState == FollowState.FOLLOWING) {
|
|
|
|
val showReblogs = menu.findItem(R.id.action_show_reblogs)
|
|
|
|
showReblogs.title = if (showingReblogs) {
|
|
|
|
getString(R.string.action_hide_reblogs)
|
|
|
|
} else {
|
|
|
|
getString(R.string.action_show_reblogs)
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
menu.removeItem(R.id.action_show_reblogs)
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// It shouldn't be possible to block or follow yourself.
|
|
|
|
menu.removeItem(R.id.action_follow)
|
|
|
|
menu.removeItem(R.id.action_block)
|
|
|
|
menu.removeItem(R.id.action_mute)
|
|
|
|
menu.removeItem(R.id.action_show_reblogs)
|
|
|
|
}
|
|
|
|
return super.onPrepareOptionsMenu(menu)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun showFollowRequestPendingDialog() {
|
|
|
|
AlertDialog.Builder(this)
|
|
|
|
.setMessage(R.string.dialog_message_cancel_follow_request)
|
|
|
|
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.changeFollowState(accountId) }
|
|
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun showUnfollowWarningDialog() {
|
|
|
|
AlertDialog.Builder(this)
|
|
|
|
.setMessage(R.string.dialog_unfollow_warning)
|
|
|
|
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.changeFollowState(accountId) }
|
|
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
|
|
.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun mention() {
|
|
|
|
loadedAccount?.let {
|
|
|
|
val intent = ComposeActivity.IntentBuilder()
|
|
|
|
.mentionedUsernames(setOf(it.username))
|
|
|
|
.build(this)
|
2018-08-23 20:57:51 +02:00
|
|
|
startActivity(intent)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onViewTag(tag: String) {
|
|
|
|
val intent = Intent(this, ViewTagActivity::class.java)
|
|
|
|
intent.putExtra("hashtag", tag)
|
2018-07-31 21:25:25 +02:00
|
|
|
startActivityWithSlideInAnimation(intent)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onViewAccount(id: String) {
|
|
|
|
val intent = Intent(this, AccountActivity::class.java)
|
|
|
|
intent.putExtra("id", id)
|
2018-07-31 21:25:25 +02:00
|
|
|
startActivityWithSlideInAnimation(intent)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onViewUrl(url: String) {
|
|
|
|
viewUrl(url)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
when (item.itemId) {
|
|
|
|
android.R.id.home -> {
|
|
|
|
onBackPressed()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
R.id.action_mention -> {
|
|
|
|
mention()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
R.id.action_open_in_web -> {
|
|
|
|
// If the account isn't loaded yet, eat the input.
|
|
|
|
if (loadedAccount != null) {
|
|
|
|
LinkHelper.openLink(loadedAccount?.url, this)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
R.id.action_follow -> {
|
|
|
|
viewModel.changeFollowState(accountId)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
R.id.action_block -> {
|
|
|
|
viewModel.changeBlockState(accountId)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
R.id.action_mute -> {
|
|
|
|
viewModel.changeMuteState(accountId)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
R.id.action_show_reblogs -> {
|
|
|
|
viewModel.changeShowReblogsState(accountId)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun getActionButton(): FloatingActionButton? {
|
|
|
|
return if (!isSelf && !blocking) {
|
|
|
|
accountFloatingActionButton
|
|
|
|
} else null
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
|
|
|
|
return dispatchingAndroidInjector
|
|
|
|
}
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
private const val KEY_ACCOUNT_ID = "id"
|
|
|
|
private val argbEvaluator = ArgbEvaluator()
|
|
|
|
|
|
|
|
@JvmStatic
|
|
|
|
fun getIntent(context: Context, accountId: String): Intent {
|
|
|
|
val intent = Intent(context, AccountActivity::class.java)
|
|
|
|
intent.putExtra(KEY_ACCOUNT_ID, accountId)
|
|
|
|
return intent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|