Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt

780 lines
31 KiB
Kotlin
Raw Normal View History

2016-07-04 03:31:17 +02:00
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 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.fragment
2016-12-04 04:58:03 +01:00
import android.accounts.AccountManager
2016-07-04 03:31:17 +02:00
import android.animation.Animator
import android.animation.Animator.AnimatorListener
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
2016-07-21 08:11:00 +02:00
import android.content.*
2016-07-04 03:31:17 +02:00
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
2016-07-21 08:46:24 +02:00
import android.database.ContentObserver
2016-07-04 03:31:17 +02:00
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
2016-07-21 08:46:24 +02:00
import android.net.Uri
2016-07-04 03:31:17 +02:00
import android.os.Bundle
2016-07-21 08:46:24 +02:00
import android.os.Handler
import android.os.Looper
2016-07-04 03:31:17 +02:00
import android.support.design.widget.NavigationView
import android.support.v4.app.LoaderManager.LoaderCallbacks
2016-07-21 08:11:00 +02:00
import android.support.v4.content.AsyncTaskLoader
2016-07-04 03:31:17 +02:00
import android.support.v4.content.Loader
import android.support.v4.view.MenuItemCompat
2016-12-05 04:39:22 +01:00
import android.support.v4.view.PagerAdapter
import android.support.v4.view.ViewPager
2016-07-04 03:31:17 +02:00
import android.support.v7.view.SupportMenuInflater
import android.support.v7.widget.ActionMenuView.OnMenuItemClickListener
import android.support.v7.widget.FixedLinearLayoutManager
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView.ViewHolder
2016-12-05 04:39:22 +01:00
import android.support.v7.widget.RecyclerViewAccessor
2016-07-04 03:31:17 +02:00
import android.view.*
import android.view.View.OnClickListener
import android.view.animation.DecelerateInterpolator
import android.widget.ImageView
2016-07-21 08:46:24 +02:00
import kotlinx.android.synthetic.main.header_drawer_account_selector.view.*
2016-12-04 06:45:57 +01:00
import org.mariotaku.ktextension.convert
2016-07-04 03:31:17 +02:00
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.ktextension.setMenuItemIcon
import org.mariotaku.ktextension.setMenuItemTitle
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.activity.*
2016-12-03 06:48:40 +01:00
import org.mariotaku.twidere.annotation.AccountType
2016-07-04 03:31:17 +02:00
import org.mariotaku.twidere.annotation.CustomTabType
import org.mariotaku.twidere.annotation.Referral
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
2016-07-21 08:11:00 +02:00
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
2016-07-04 03:31:17 +02:00
import org.mariotaku.twidere.menu.AccountToggleProvider
2016-12-04 04:58:03 +01:00
import org.mariotaku.twidere.model.AccountDetails
2016-07-04 03:31:17 +02:00
import org.mariotaku.twidere.model.SupportTabSpec
import org.mariotaku.twidere.model.UserKey
2016-12-04 04:58:03 +01:00
import org.mariotaku.twidere.model.util.AccountUtils
2016-07-04 03:31:17 +02:00
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts
2016-07-21 08:11:00 +02:00
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
2016-07-04 03:31:17 +02:00
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback
import org.mariotaku.twidere.view.ShapedImageView
import java.util.*
2016-07-21 08:11:00 +02:00
class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks<AccountsInfo>, OnSharedPreferenceChangeListener, OnClickListener, KeyboardShortcutCallback, NavigationView.OnNavigationItemSelectedListener {
2016-07-04 03:31:17 +02:00
private val mSystemWindowsInsets = Rect()
private var mResolver: ContentResolver? = null
2016-12-05 04:39:22 +01:00
private var accountsAdapter: AccountSelectorAdapter? = null
2016-07-21 08:46:24 +02:00
2016-12-05 04:39:22 +01:00
private val accountsSelector by lazy { accountsHeader.otherAccountsList }
2016-07-21 08:46:24 +02:00
private val navigationView by lazy { view as NavigationView }
private val accountsHeader by lazy { navigationView.getHeaderView(0) }
private val accountProfileBanner by lazy { accountsHeader.accountProfileBanner }
private val floatingProfileImageSnapshot by lazy { accountsHeader.floatingProfileImageSnapshot }
private val accountProfileImageView by lazy { accountsHeader.profileImage }
private val accountProfileNameView by lazy { accountsHeader.name }
private val accountProfileScreenNameView by lazy { accountsHeader.screenName }
private val accountDashboardMenu by lazy { accountsHeader.accountDashboardMenu }
private val profileContainer by lazy { accountsHeader.profileContainer }
private val noAccountContainer by lazy { accountsHeader.noAccountContainer }
2016-07-04 03:31:17 +02:00
2016-12-05 04:39:22 +01:00
private var accountActionProvider: AccountToggleProvider? = null
2016-07-21 08:46:24 +02:00
2016-12-05 04:39:22 +01:00
private var switchAccountAnimationPlaying: Boolean = false
private var useStarsForLikes: Boolean = false
private var loaderInitialized: Boolean = false
2016-07-04 03:31:17 +02:00
2016-12-05 04:39:22 +01:00
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mResolver = contentResolver
val inflater = getLayoutInflater(savedInstanceState)
accountsAdapter = AccountSelectorAdapter(inflater, this)
val layoutManager = FixedLinearLayoutManager(context)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
layoutManager.stackFromEnd = true
accountsSelector.adapter = accountsAdapter
accountsSelector.setPageTransformer(false, AccountsSelectorTransformer)
val menuInflater = SupportMenuInflater(context)
menuInflater.inflate(R.menu.action_dashboard_timeline_toggle, accountDashboardMenu.menu)
accountDashboardMenu.setOnMenuItemClickListener(OnMenuItemClickListener { item ->
if (item.groupId != AccountToggleProvider.MENU_GROUP) {
when (item.itemId) {
R.id.compose -> {
val account = accountsAdapter!!.selectedAccount ?: return@OnMenuItemClickListener true
val composeIntent = Intent(INTENT_ACTION_COMPOSE)
composeIntent.setClass(activity, ComposeActivity::class.java)
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
startActivity(composeIntent)
return@OnMenuItemClickListener true
}
}
return@OnMenuItemClickListener false
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
val accounts = accountActionProvider!!.accounts
val account = accounts[item.order]
val values = ContentValues()
val newActivated = !account.activated
accountActionProvider!!.setAccountActivated(account.key, newActivated)
values.put(Accounts.IS_ACTIVATED, newActivated)
val where = Expression.equalsArgs(Accounts.ACCOUNT_KEY).sql
val whereArgs = arrayOf(account.key.toString())
mResolver!!.update(Accounts.CONTENT_URI, values, where, whereArgs)
true
})
profileContainer.setOnClickListener(this)
accountProfileBanner.setInAnimation(context, android.R.anim.fade_in)
accountProfileBanner.setOutAnimation(context, android.R.anim.fade_out)
accountProfileBanner.setFactory {
inflater.inflate(R.layout.layout_account_dashboard_profile_image,
accountProfileBanner, false)
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
navigationView.setNavigationItemSelectedListener(this)
preferences.registerOnSharedPreferenceChangeListener(this)
loadAccounts()
updateSystemWindowsInsets()
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
override fun onStart() {
super.onStart()
loaderManager.restartLoader(0, null, this)
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
override fun onResume() {
super.onResume()
updateDefaultAccountState()
}
override fun onStop() {
super.onStop()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_accounts_dashboard, container, false)
2016-07-04 03:31:17 +02:00
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_SETTINGS -> {
if (data == null) return
2016-07-26 09:12:25 +02:00
if (data.getBooleanExtra(EXTRA_SHOULD_RESTART, false)) {
Utils.restartActivity(activity)
} else if (data.getBooleanExtra(EXTRA_SHOULD_RECREATE, false)) {
2016-07-04 03:31:17 +02:00
activity.recreate()
}
return
}
}
super.onActivityResult(requestCode, resultCode, data)
}
2016-12-05 04:39:22 +01:00
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler,
keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
return false
}
override fun isKeyboardShortcutHandled(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
val action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState)
return ACTION_NAVIGATION_PREVIOUS == action || ACTION_NAVIGATION_NEXT == action
}
override fun handleKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler, keyCode: Int,
repeatCount: Int, event: KeyEvent, metaState: Int): Boolean {
return true
2016-07-04 03:31:17 +02:00
}
override fun onClick(v: View) {
when (v.id) {
R.id.profileContainer -> {
2016-12-05 04:39:22 +01:00
val account = accountsAdapter!!.selectedAccount ?: return
2016-07-04 03:31:17 +02:00
val activity = activity
2016-12-04 04:58:03 +01:00
if (account.user != null) {
IntentUtils.openUserProfile(activity, account.user!!, null,
2016-07-04 03:31:17 +02:00
preferences.getBoolean(KEY_NEW_DOCUMENT_API),
Referral.SELF_PROFILE)
} else {
2016-12-04 04:58:03 +01:00
IntentUtils.openUserProfile(activity, account.key, account.key,
account.user.screen_name, null,
2016-07-04 03:31:17 +02:00
preferences.getBoolean(KEY_NEW_DOCUMENT_API),
Referral.SELF_PROFILE)
}
}
}
}
2016-07-21 08:11:00 +02:00
override fun onCreateLoader(id: Int, args: Bundle?): Loader<AccountsInfo> {
return AccountsInfoLoader(activity)
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
2016-07-21 08:11:00 +02:00
override fun onLoadFinished(loader: Loader<AccountsInfo>, data: AccountsInfo) {
2016-07-04 03:31:17 +02:00
updateAccountProviderData(data)
}
2016-07-21 08:11:00 +02:00
private fun updateAccountProviderData(data: AccountsInfo) {
2016-07-21 08:46:24 +02:00
val menu = accountDashboardMenu.menu
2016-12-05 04:39:22 +01:00
accountActionProvider = MenuItemCompat.getActionProvider(menu.findItem(R.id.select_account)) as AccountToggleProvider
2016-07-21 08:11:00 +02:00
val accounts = data.accounts
2016-12-04 04:58:03 +01:00
if (accounts.isNotEmpty()) {
2016-07-21 08:46:24 +02:00
noAccountContainer.visibility = View.GONE
profileContainer.visibility = View.VISIBLE
2016-07-04 03:31:17 +02:00
} else {
2016-07-21 08:46:24 +02:00
noAccountContainer.visibility = View.VISIBLE
profileContainer.visibility = View.INVISIBLE
2016-07-04 03:31:17 +02:00
}
var defaultId: UserKey? = null
for (account in accounts) {
2016-12-04 04:58:03 +01:00
if (account.activated) {
defaultId = account.key
2016-07-04 03:31:17 +02:00
break
}
}
2016-12-05 04:39:22 +01:00
useStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)
2016-07-04 03:31:17 +02:00
2016-12-05 04:39:22 +01:00
accountsAdapter!!.accounts = accounts
2016-12-04 06:45:57 +01:00
var accountKey = preferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null)?.convert(UserKey::valueOf)
2016-07-04 03:31:17 +02:00
if (accountKey == null) {
accountKey = defaultId
}
2016-12-04 04:58:03 +01:00
var selectedAccount: AccountDetails? = null
2016-07-04 03:31:17 +02:00
for (account in accounts) {
2016-12-04 04:58:03 +01:00
if (account.key.maybeEquals(accountKey)) {
2016-07-04 03:31:17 +02:00
selectedAccount = account
break
}
}
2016-12-05 04:39:22 +01:00
accountsAdapter!!.selectedAccount = selectedAccount
2016-07-04 03:31:17 +02:00
2016-12-05 04:39:22 +01:00
if (accountActionProvider != null) {
accountActionProvider!!.isExclusive = false
accountActionProvider!!.accounts = accounts
2016-07-04 03:31:17 +02:00
}
updateAccountActions()
2016-12-05 04:39:22 +01:00
val currentAccount = accountsAdapter!!.selectedAccount
2016-07-04 03:31:17 +02:00
if (currentAccount != null) {
displayAccountBanner(currentAccount)
displayCurrentAccount(null)
}
updateDefaultAccountState()
2016-07-21 08:11:00 +02:00
if (data.draftsCount > 0) {
navigationView.menu.findItem(R.id.drafts).title = "${getString(R.string.drafts)} (${data.draftsCount})"
} else {
navigationView.menu.findItem(R.id.drafts).title = getString(R.string.drafts)
}
2016-07-04 03:31:17 +02:00
}
2016-07-21 08:11:00 +02:00
override fun onLoaderReset(loader: Loader<AccountsInfo>) {
2016-07-04 03:31:17 +02:00
}
2016-07-06 15:21:34 +02:00
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
2016-07-04 03:31:17 +02:00
if (KEY_DEFAULT_ACCOUNT_KEY == key) {
updateDefaultAccountState()
}
}
override fun fitSystemWindows(insets: Rect) {
mSystemWindowsInsets.set(insets)
updateSystemWindowsInsets()
}
private fun updateSystemWindowsInsets() {
}
fun loadAccounts() {
2016-12-05 04:39:22 +01:00
if (!loaderInitialized) {
loaderInitialized = true
2016-07-04 03:31:17 +02:00
loaderManager.initLoader(0, null, this)
} else {
loaderManager.restartLoader(0, null, this)
}
}
internal fun updateAccountActions() {
2016-08-25 04:10:53 +02:00
val activity = activity as HomeActivity
2016-07-04 03:31:17 +02:00
val tabs = activity.tabs
2016-12-05 04:39:22 +01:00
val account = accountsAdapter!!.selectedAccount ?: return
2016-07-04 03:31:17 +02:00
var hasDmTab = false
var hasInteractionsTab = false
for (tab in tabs) {
if (tab.type == null) continue
when (tab.type) {
CustomTabType.DIRECT_MESSAGES -> {
if (!hasDmTab) {
2016-12-04 04:58:03 +01:00
hasDmTab = hasAccountInTab(tab, account.key, account.activated)
2016-07-04 03:31:17 +02:00
}
}
CustomTabType.NOTIFICATIONS_TIMELINE -> {
if (!hasInteractionsTab) {
2016-12-04 04:58:03 +01:00
hasInteractionsTab = hasAccountInTab(tab, account.key, account.activated)
2016-07-04 03:31:17 +02:00
}
}
}
}
2016-07-21 08:11:00 +02:00
val menu = navigationView.menu
2016-07-04 03:31:17 +02:00
menu.setItemAvailability(R.id.interactions, !hasInteractionsTab)
menu.setItemAvailability(R.id.messages, !hasDmTab)
2016-12-05 04:39:22 +01:00
if (useStarsForLikes) {
2016-07-04 03:31:17 +02:00
menu.setMenuItemTitle(R.id.favorites, R.string.favorites)
menu.setMenuItemIcon(R.id.favorites, R.drawable.ic_action_star)
} else {
menu.setMenuItemTitle(R.id.favorites, R.string.likes)
menu.setMenuItemIcon(R.id.favorites, R.drawable.ic_action_heart)
}
var hasLists = false
var hasGroups = false
var hasPublicTimeline = false
2016-12-04 06:45:57 +01:00
when (account.type) {
2016-12-03 06:48:40 +01:00
AccountType.TWITTER -> {
2016-07-04 03:31:17 +02:00
hasLists = true
}
2016-12-03 06:48:40 +01:00
AccountType.STATUSNET -> {
2016-07-04 03:31:17 +02:00
hasGroups = true
}
2016-12-03 06:48:40 +01:00
AccountType.FANFOU -> {
2016-07-04 03:31:17 +02:00
hasPublicTimeline = true
}
}
MenuUtils.setItemAvailability(menu, R.id.groups, hasGroups)
MenuUtils.setItemAvailability(menu, R.id.lists, hasLists)
MenuUtils.setItemAvailability(menu, R.id.public_timeline, hasPublicTimeline)
}
private fun hasAccountInTab(tab: SupportTabSpec, accountId: UserKey, isActivated: Boolean): Boolean {
if (tab.args == null) return false
val accountKeys = Utils.getAccountKeys(context, tab.args) ?: return isActivated
2016-08-17 15:46:18 +02:00
return accountKeys.contains(accountId)
2016-07-04 03:31:17 +02:00
}
private fun closeAccountsDrawer() {
2016-12-05 04:39:22 +01:00
val activity = activity as? HomeActivity ?: return
activity.closeAccountsDrawer()
2016-07-04 03:31:17 +02:00
}
private fun getLocationOnScreen(view: View, rectF: RectF) {
val location = IntArray(2)
view.getLocationOnScreen(location)
rectF.set(location[0].toFloat(), location[1].toFloat(), (location[0] + view.width).toFloat(), (location[1] + view.height).toFloat())
}
2016-12-04 04:58:03 +01:00
private fun onAccountSelected(holder: AccountProfileImageViewHolder, account: AccountDetails) {
2016-12-05 04:39:22 +01:00
if (switchAccountAnimationPlaying) return
2016-07-21 08:46:24 +02:00
val snapshotView = floatingProfileImageSnapshot
val profileImageView = accountProfileImageView
2016-07-04 03:31:17 +02:00
val clickedImageView = holder.iconView
// Reset snapshot view position
snapshotView.pivotX = 0f
snapshotView.pivotY = 0f
snapshotView.translationX = 0f
snapshotView.translationY = 0f
val matrix = Matrix()
val sourceBounds = RectF()
val destBounds = RectF()
val snapshotBounds = RectF()
getLocationOnScreen(clickedImageView, sourceBounds)
getLocationOnScreen(profileImageView, destBounds)
getLocationOnScreen(snapshotView, snapshotBounds)
val finalScale = destBounds.width() / sourceBounds.width()
val snapshotBitmap = TransitionUtils.createViewBitmap(clickedImageView, matrix,
RectF(0f, 0f, sourceBounds.width(), sourceBounds.height()))
val lp = snapshotView.layoutParams
lp.width = clickedImageView.width
lp.height = clickedImageView.height
snapshotView.layoutParams = lp
// Copied from MaterialNavigationDrawer: https://github.com/madcyph3r/AdvancedMaterialDrawer/
val set = AnimatorSet()
set.play(ObjectAnimator.ofFloat(snapshotView, View.TRANSLATION_X, sourceBounds.left - snapshotBounds.left, destBounds.left - snapshotBounds.left))
.with(ObjectAnimator.ofFloat(snapshotView, View.TRANSLATION_Y, sourceBounds.top - snapshotBounds.top, destBounds.top - snapshotBounds.top))
.with(ObjectAnimator.ofFloat<View>(snapshotView, View.SCALE_X, 1f, finalScale))
.with(ObjectAnimator.ofFloat<View>(snapshotView, View.SCALE_Y, 1f, finalScale))
.with(ObjectAnimator.ofFloat<View>(profileImageView, View.ALPHA, 1f, 0f))
.with(ObjectAnimator.ofFloat<View>(clickedImageView, View.SCALE_X, 0f, 1f))
.with(ObjectAnimator.ofFloat<View>(clickedImageView, View.SCALE_Y, 0f, 1f))
val animationTransition: Long = 400
set.duration = animationTransition
set.interpolator = DecelerateInterpolator()
set.addListener(object : AnimatorListener {
private var clickedDrawable: Drawable? = null
private var clickedColors: IntArray? = null
override fun onAnimationStart(animation: Animator) {
snapshotView.visibility = View.VISIBLE
snapshotView.setImageBitmap(snapshotBitmap)
2016-07-21 08:46:24 +02:00
val profileDrawable = profileImageView.drawable
2016-07-04 03:31:17 +02:00
clickedDrawable = clickedImageView.drawable
clickedColors = clickedImageView.borderColors
2016-12-05 04:39:22 +01:00
val oldSelectedAccount = accountsAdapter!!.selectedAccount ?: return
2016-07-04 03:31:17 +02:00
mediaLoader.displayDashboardProfileImage(clickedImageView,
oldSelectedAccount, profileDrawable)
clickedImageView.setBorderColors(*profileImageView.borderColors)
displayAccountBanner(account)
2016-12-05 04:39:22 +01:00
switchAccountAnimationPlaying = true
2016-07-04 03:31:17 +02:00
}
override fun onAnimationEnd(animation: Animator) {
finishAnimation()
}
override fun onAnimationCancel(animation: Animator) {
finishAnimation()
}
override fun onAnimationRepeat(animation: Animator) {
}
private fun finishAnimation() {
2016-12-05 04:39:22 +01:00
preferences.edit()
.putString(KEY_DEFAULT_ACCOUNT_KEY, account.key.toString())
.apply()
accountsAdapter!!.selectedAccount = account
2016-07-04 03:31:17 +02:00
updateAccountActions()
displayCurrentAccount(clickedDrawable)
snapshotView.visibility = View.INVISIBLE
snapshotView.setImageDrawable(null)
2016-07-21 08:46:24 +02:00
profileImageView.setImageDrawable(clickedDrawable)
2016-07-04 03:31:17 +02:00
profileImageView.setBorderColors(*clickedColors!!)
profileImageView.alpha = 1f
clickedImageView.scaleX = 1f
clickedImageView.scaleY = 1f
clickedImageView.alpha = 1f
2016-12-05 04:39:22 +01:00
switchAccountAnimationPlaying = false
2016-07-04 03:31:17 +02:00
}
})
set.start()
}
2016-12-04 04:58:03 +01:00
protected fun displayAccountBanner(account: AccountDetails) {
2016-07-21 08:46:24 +02:00
val bannerWidth = accountProfileBanner.width
2016-07-04 03:31:17 +02:00
val res = resources
val defWidth = res.displayMetrics.widthPixels
val width = if (bannerWidth > 0) bannerWidth else defWidth
2016-07-21 08:46:24 +02:00
val bannerView = accountProfileBanner.nextView as ImageView
2016-07-04 03:31:17 +02:00
if (bannerView.drawable == null || !CompareUtils.objectEquals(account, bannerView.tag)) {
mediaLoader.displayProfileBanner(bannerView, account, width)
bannerView.tag = account
} else {
mediaLoader.cancelDisplayTask(bannerView)
}
}
private fun displayCurrentAccount(profileImageSnapshot: Drawable?) {
2016-12-05 04:39:22 +01:00
val account = accountsAdapter!!.selectedAccount ?: return
2016-12-04 04:58:03 +01:00
accountProfileNameView.text = account.user.name
accountProfileScreenNameView.text = String.format("@%s", account.user.screen_name)
2016-07-21 08:46:24 +02:00
mediaLoader.displayDashboardProfileImage(accountProfileImageView, account,
2016-07-04 03:31:17 +02:00
profileImageSnapshot)
2016-07-21 08:46:24 +02:00
accountProfileImageView.setBorderColors(account.color)
accountProfileBanner.showNext()
2016-07-04 03:31:17 +02:00
}
private fun updateDefaultAccountState() {
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
2016-12-05 04:39:22 +01:00
val account = accountsAdapter!!.selectedAccount ?: return false
2016-07-04 03:31:17 +02:00
when (item.itemId) {
R.id.search -> {
val intent = Intent(activity, QuickSearchBarActivity::class.java)
2016-12-04 04:58:03 +01:00
intent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
2016-07-04 03:31:17 +02:00
startActivity(intent)
closeAccountsDrawer()
}
R.id.compose -> {
val composeIntent = Intent(INTENT_ACTION_COMPOSE)
composeIntent.setClass(activity, ComposeActivity::class.java)
2016-12-04 04:58:03 +01:00
composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
2016-07-04 03:31:17 +02:00
startActivity(composeIntent)
}
R.id.favorites -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openUserFavorites(activity, account.key,
account.key, account.user.screen_name)
2016-07-04 03:31:17 +02:00
}
R.id.lists -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openUserLists(activity, account.key,
account.key, account.user.screen_name)
2016-07-04 03:31:17 +02:00
}
R.id.groups -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openUserGroups(activity, account.key,
account.key, account.user.screen_name)
2016-07-04 03:31:17 +02:00
}
R.id.public_timeline -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openPublicTimeline(activity, account.key)
2016-07-04 03:31:17 +02:00
}
R.id.messages -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openDirectMessages(activity, account.key)
2016-07-04 03:31:17 +02:00
}
R.id.interactions -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openInteractions(activity, account.key)
2016-07-04 03:31:17 +02:00
}
R.id.edit -> {
2016-12-04 04:58:03 +01:00
IntentUtils.openProfileEditor(activity, account.key)
2016-07-04 03:31:17 +02:00
}
R.id.accounts -> {
IntentUtils.openAccountsManager(activity)
closeAccountsDrawer()
}
R.id.drafts -> {
IntentUtils.openDrafts(activity)
closeAccountsDrawer()
}
R.id.filters -> {
IntentUtils.openFilters(activity)
closeAccountsDrawer()
}
R.id.plus_service -> {
val intent = Intent(activity, PlusServiceDashboardActivity::class.java)
startActivity(intent)
closeAccountsDrawer()
}
R.id.settings -> {
val intent = Intent(activity, SettingsActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
startActivityForResult(intent, REQUEST_SETTINGS)
closeAccountsDrawer()
}
}
return false
}
fun setStatusBarHeight(height: Int) {
val top = Utils.getInsetsTopWithoutActionBarHeight(activity, height)
2016-07-21 08:46:24 +02:00
profileContainer.setPadding(0, top, 0, 0)
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
fun shouldDisableDrawerSlide(e: MotionEvent): Boolean {
if (accountsSelector == null) return false
return TwidereViewUtils.hitView(e.rawX, e.rawY, accountsSelector)
}
2016-07-04 03:31:17 +02:00
internal class AccountProfileImageViewHolder(val adapter: AccountSelectorAdapter, itemView: View) : ViewHolder(itemView), OnClickListener {
2016-12-05 04:39:22 +01:00
2016-07-04 03:31:17 +02:00
val iconView: ShapedImageView
init {
itemView.setOnClickListener(this)
iconView = itemView.findViewById(android.R.id.icon) as ShapedImageView
}
override fun onClick(v: View) {
adapter.dispatchItemSelected(this)
}
2016-12-05 04:39:22 +01:00
2016-07-04 03:31:17 +02:00
}
internal class AccountSelectorAdapter(
private val inflater: LayoutInflater,
private val fragment: AccountsDashboardFragment
2016-12-05 04:39:22 +01:00
) : PagerAdapter() {
2016-07-04 03:31:17 +02:00
private val mediaLoader: MediaLoaderWrapper
2016-12-05 04:39:22 +01:00
2016-12-04 04:58:03 +01:00
var accounts: Array<AccountDetails>? = null
2016-07-04 03:31:17 +02:00
set(value) {
if (value != null) {
val previousAccounts = accounts
if (previousAccounts != null) {
val tmpList = arrayListOf(*value)
2016-12-04 04:58:03 +01:00
val tmpResult = ArrayList<AccountDetails>()
2016-07-04 03:31:17 +02:00
previousAccounts.forEach { previousAccount ->
val prefIndexOfTmp = tmpList.indexOfFirst { previousAccount == it }
if (prefIndexOfTmp >= 0) {
tmpResult.add(tmpList.removeAt(prefIndexOfTmp))
}
}
tmpResult.addAll(tmpList)
field = tmpResult.toTypedArray()
} else {
field = value
}
} else {
field = null
}
notifyDataSetChanged()
}
init {
mediaLoader = fragment.mediaLoader
}
2016-12-05 04:39:22 +01:00
fun getAdapterAccount(position: Int): AccountDetails? {
return accounts?.getOrNull(position + 1)
2016-07-04 03:31:17 +02:00
}
2016-12-04 04:58:03 +01:00
var selectedAccount: AccountDetails?
2016-07-04 03:31:17 +02:00
get() {
2016-12-05 04:39:22 +01:00
return accounts?.firstOrNull()
2016-07-04 03:31:17 +02:00
}
set(account) {
val selectedAccount = selectedAccount
if (selectedAccount == null || account == null) return
swap(account, selectedAccount)
}
2016-12-05 04:39:22 +01:00
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val view = inflater.inflate(R.layout.adapter_item_dashboard_account, container, false)
container.addView(view)
val holder = AccountProfileImageViewHolder(this, view)
2016-12-05 05:53:04 +01:00
val account = getAdapterAccount(position)!!
holder.iconView.setBorderColor(account.color)
mediaLoader.displayDashboardProfileImage(holder.iconView, account, null)
2016-12-05 04:39:22 +01:00
RecyclerViewAccessor.setLayoutPosition(holder, position)
return holder
}
override fun destroyItem(container: ViewGroup, position: Int, obj: Any?) {
container.removeView((obj as AccountProfileImageViewHolder).itemView)
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
override fun isViewFromObject(view: View?, obj: Any?): Boolean {
return view == (obj as AccountProfileImageViewHolder).itemView
2016-07-04 03:31:17 +02:00
}
2016-12-05 04:39:22 +01:00
override fun getCount(): Int {
2016-12-04 04:58:03 +01:00
if (accounts == null || accounts!!.isEmpty()) return 0
2016-07-04 03:31:17 +02:00
return accounts!!.size - 1
}
2016-12-05 04:39:22 +01:00
override fun getPageWidth(position: Int): Float {
2016-12-05 05:53:04 +01:00
return 1f / AccountsSelectorTransformer.selectorAccountsCount
2016-12-05 04:39:22 +01:00
}
2016-07-04 03:31:17 +02:00
fun dispatchItemSelected(holder: AccountProfileImageViewHolder) {
2016-12-05 04:39:22 +01:00
fragment.onAccountSelected(holder, getAdapterAccount(holder.layoutPosition)!!)
2016-07-04 03:31:17 +02:00
}
2016-12-04 04:58:03 +01:00
private fun swap(from: AccountDetails, to: AccountDetails) {
2016-07-04 03:31:17 +02:00
val accounts = accounts ?: return
val fromIdx = accounts.indexOfFirst { it == from }
val toIdx = accounts.indexOfFirst { it == to }
if (fromIdx < 0 || toIdx < 0) return
val temp = accounts[toIdx]
accounts[toIdx] = accounts[fromIdx]
accounts[fromIdx] = temp
notifyDataSetChanged()
}
2016-12-05 04:39:22 +01:00
2016-07-04 03:31:17 +02:00
}
2016-07-21 08:11:00 +02:00
data class AccountsInfo(
2016-12-04 04:58:03 +01:00
val accounts: Array<AccountDetails>,
2016-07-21 08:11:00 +02:00
val draftsCount: Int
)
2016-07-04 03:31:17 +02:00
2016-07-21 08:11:00 +02:00
class AccountsInfoLoader(context: Context) : AsyncTaskLoader<AccountsInfo>(context) {
2016-07-21 08:46:24 +02:00
private var contentObserver: ContentObserver? = null
2016-12-05 04:39:22 +01:00
2016-07-21 08:46:24 +02:00
private var firstLoad: Boolean
init {
firstLoad = true
}
2016-07-21 08:11:00 +02:00
override fun loadInBackground(): AccountsInfo {
2016-12-04 04:58:03 +01:00
val accounts = AccountUtils.getAllAccountDetails(AccountManager.get(context))
val draftsCount = DataStoreUtils.queryCount(context, Drafts.CONTENT_URI_UNSENT, null, null)
2016-07-21 08:11:00 +02:00
return AccountsInfo(accounts, draftsCount)
}
2016-07-04 03:31:17 +02:00
2016-07-21 08:46:24 +02:00
/**
* Handles a request to completely reset the Loader.
*/
override fun onReset() {
super.onReset()
// Ensure the loader is stopped
onStopLoading()
// Stop monitoring for changes.
if (contentObserver != null) {
val cr = context.contentResolver
cr.unregisterContentObserver(contentObserver)
contentObserver = null
}
}
/**
* Handles a request to start the Loader.
*/
2016-07-21 08:11:00 +02:00
override fun onStartLoading() {
2016-07-21 08:46:24 +02:00
// Start watching for changes in the app data.
if (contentObserver == null) {
contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean) {
onContentChanged()
}
override fun onChange(selfChange: Boolean, uri: Uri?) {
onContentChanged()
}
}
val cr = context.contentResolver
cr.registerContentObserver(Accounts.CONTENT_URI, true, contentObserver)
cr.registerContentObserver(Drafts.CONTENT_URI, true, contentObserver)
}
if (takeContentChanged() || firstLoad) {
firstLoad = false
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad()
}
}
/**
* Handles a request to stop the Loader.
*/
override fun onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad()
2016-07-21 08:11:00 +02:00
}
2016-12-05 04:39:22 +01:00
}
object AccountsSelectorTransformer : ViewPager.PageTransformer {
2016-12-05 05:53:04 +01:00
const internal val selectorAccountsCount: Int = 3
2016-12-05 04:39:22 +01:00
override fun transformPage(page: View, position: Float) {
if (position < 0) {
2016-12-05 05:53:04 +01:00
page.alpha = 1 + position * selectorAccountsCount
} else if (position > (selectorAccountsCount - 1f) / selectorAccountsCount) {
page.alpha = (1 - position) * selectorAccountsCount
2016-12-05 04:39:22 +01:00
} else {
page.alpha = 1f
}
}
2016-07-21 08:11:00 +02:00
}
2016-12-05 04:39:22 +01:00
}