Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt

1103 lines
45 KiB
Kotlin
Raw Normal View History

2016-07-02 05:54:53 +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.activity
import android.accounts.Account
import android.accounts.AccountManager
import android.accounts.OnAccountsUpdateListener
2017-08-30 05:59:57 +02:00
import android.annotation.SuppressLint
2016-12-17 05:10:24 +01:00
import android.app.Dialog
2016-07-02 05:54:53 +02:00
import android.app.PendingIntent
import android.app.SearchManager
import android.content.Context
import android.content.DialogInterface
2016-07-02 05:54:53 +02:00
import android.content.Intent
2016-12-24 15:05:15 +01:00
import android.content.SharedPreferences
2016-07-02 05:54:53 +02:00
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.AsyncTask
2017-06-25 17:01:33 +02:00
import android.os.Build
2016-07-02 05:54:53 +02:00
import android.os.Bundle
import android.util.SparseIntArray
import android.view.Gravity
import android.view.KeyEvent
import android.view.MenuItem
import android.view.View
2016-07-02 05:54:53 +02:00
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener
import android.view.ViewGroup.MarginLayoutParams
2020-05-12 09:20:12 +02:00
import android.widget.RelativeLayout
import androidx.annotation.StringRes
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.TintTypedArray
import androidx.core.app.NotificationCompat
import androidx.core.view.*
import androidx.drawerlayout.widget.DrawerLayout
import androidx.drawerlayout.widget.DrawerLayoutAccessor
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
2016-12-13 12:35:25 +01:00
import com.getkeepsafe.taptargetview.TapTarget
import com.getkeepsafe.taptargetview.TapTargetView
2016-07-02 05:54:53 +02:00
import com.squareup.otto.Subscribe
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.activity_home_content.*
import kotlinx.android.synthetic.main.layout_empty_tab_hint.*
2017-04-14 13:28:09 +02:00
import nl.komponents.kovenant.task
2016-12-22 11:21:17 +01:00
import org.mariotaku.chameleon.ChameleonUtils
2017-08-30 05:59:57 +02:00
import org.mariotaku.kpreferences.contains
2016-12-13 12:35:25 +01:00
import org.mariotaku.kpreferences.get
import org.mariotaku.kpreferences.set
import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe
import org.mariotaku.ktextension.coerceInOr
import org.mariotaku.ktextension.contains
import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe
2017-04-10 11:35:35 +02:00
import org.mariotaku.sqliteqb.library.Expression
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.Constants.*
import org.mariotaku.twidere.R
2017-02-16 07:50:25 +01:00
import org.mariotaku.twidere.activity.iface.IControlBarActivity.ControlBarShowHideHelper
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.adapter.SupportTabsAdapter
import org.mariotaku.twidere.annotation.CustomTabType
2017-09-10 17:32:12 +02:00
import org.mariotaku.twidere.annotation.FilterScope
2017-06-25 17:01:33 +02:00
import org.mariotaku.twidere.annotation.NavbarStyle
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.annotation.ReadPositionTag
import org.mariotaku.twidere.constant.*
2017-02-05 14:42:20 +01:00
import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.extension.model.notificationBuilder
2017-06-19 15:45:41 +02:00
import org.mariotaku.twidere.extension.onShow
2017-02-16 07:50:25 +01:00
import org.mariotaku.twidere.fragment.AccountsDashboardFragment
import org.mariotaku.twidere.fragment.BaseDialogFragment
2017-02-15 07:48:10 +01:00
import org.mariotaku.twidere.fragment.iface.IFloatingActionButtonFragment
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback
import org.mariotaku.twidere.graphic.EmptyDrawable
2016-12-04 06:45:57 +01:00
import org.mariotaku.twidere.model.AccountDetails
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.model.SupportTabSpec
2016-12-01 08:55:38 +01:00
import org.mariotaku.twidere.model.Tab
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.model.UserKey
2017-02-09 09:00:12 +01:00
import org.mariotaku.twidere.model.event.UnreadCountUpdatedEvent
import org.mariotaku.twidere.model.notification.NotificationChannelSpec
import org.mariotaku.twidere.provider.TwidereDataStore.Activities
2017-03-13 06:35:11 +01:00
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
2017-03-13 08:13:39 +01:00
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
2017-09-16 18:35:21 +02:00
import org.mariotaku.twidere.receiver.NotificationReceiver
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback
2017-08-30 05:59:57 +02:00
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
2016-07-02 05:54:53 +02:00
import org.mariotaku.twidere.view.HomeDrawerLayout
import org.mariotaku.twidere.view.TabPagerIndicator
import java.lang.ref.WeakReference
2020-06-09 00:50:51 +02:00
import kotlin.math.floor
2016-07-02 05:54:53 +02:00
2017-01-17 18:59:44 +01:00
class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, SupportFragmentCallback,
OnLongClickListener, DrawerLayout.DrawerListener {
2016-07-02 05:54:53 +02:00
2016-12-12 14:19:02 +01:00
private val accountUpdatedListener = AccountUpdatedListener(this)
2016-07-02 05:54:53 +02:00
2016-12-04 06:45:57 +01:00
private var selectedAccountToSearch: AccountDetails? = null
2016-07-02 05:54:53 +02:00
2016-12-06 02:26:53 +01:00
private lateinit var multiSelectHandler: MultiSelectEventHandler
private lateinit var pagerAdapter: SupportTabsAdapter
private lateinit var drawerToggle: ActionBarDrawerToggle
2016-07-02 05:54:53 +02:00
private var propertiesInitialized = false
2017-06-25 17:01:33 +02:00
private var actionsButtonBottomMargin: Int = 0
2016-07-02 05:54:53 +02:00
private var updateUnreadCountTask: UpdateUnreadCountTask? = null
private val readStateChangeListener = OnSharedPreferenceChangeListener { _, _ -> updateUnreadCount() }
2017-02-16 07:50:25 +01:00
private val controlBarShowHideHelper = ControlBarShowHideHelper(this)
override val controlBarHeight: Int
get() {
return mainTabs.height - mainTabs.stripHeight
}
override val currentVisibleFragment: Fragment?
get() {
val currentItem = mainPager.currentItem
if (currentItem < 0 || currentItem >= pagerAdapter.count) return null
return pagerAdapter.instantiateItem(mainPager, currentItem)
}
2016-07-02 05:54:53 +02:00
private val homeDrawerToggleDelegate = object : ActionBarDrawerToggle.Delegate {
override fun setActionBarUpIndicator(upDrawable: Drawable, @StringRes contentDescRes: Int) {
drawerToggleButton.setImageDrawable(upDrawable)
2016-12-22 11:21:17 +01:00
drawerToggleButton.setColorFilter(ChameleonUtils.getColorDependent(overrideTheme.colorToolbar))
2016-07-02 05:54:53 +02:00
drawerToggleButton.contentDescription = getString(contentDescRes)
}
override fun setActionBarDescription(@StringRes contentDescRes: Int) {
drawerToggleButton.contentDescription = getString(contentDescRes)
}
2017-08-30 05:59:57 +02:00
@SuppressLint("RestrictedApi")
2016-07-02 05:54:53 +02:00
override fun getThemeUpIndicator(): Drawable {
2016-12-22 11:21:17 +01:00
val a = TintTypedArray.obtainStyledAttributes(actionBarThemedContext, null,
HOME_AS_UP_ATTRS)
2016-07-02 05:54:53 +02:00
val result = a.getDrawable(0)
a.recycle()
return result
}
override fun getActionBarThemedContext(): Context {
return toolbar.context
2016-07-02 05:54:53 +02:00
}
override fun isNavigationVisible(): Boolean {
return true
}
}
private val keyboardShortcutRecipient: Fragment?
get() = when {
homeMenu.isDrawerOpen(GravityCompat.START) -> leftDrawerFragment
homeMenu.isDrawerOpen(GravityCompat.END) -> null
else -> currentVisibleFragment
}
2016-12-03 16:45:13 +01:00
private val activatedAccountKeys: Array<UserKey>
get() = DataStoreUtils.getActivatedAccountKeys(this)
2016-07-02 05:54:53 +02:00
private val leftDrawerFragment: Fragment?
2016-07-02 05:54:53 +02:00
get() = supportFragmentManager.findFragmentById(R.id.leftDrawer)
private val isDrawerOpen: Boolean
get() {
val drawer = homeMenu ?: return false
return drawer.isDrawerOpen(GravityCompat.START) || drawer.isDrawerOpen(GravityCompat.END)
}
/**
* Called when the context is first created.
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
multiSelectHandler = MultiSelectEventHandler(this)
2016-12-06 02:26:53 +01:00
multiSelectHandler.dispatchOnCreate()
DataStoreUtils.prepareDatabase(this)
2016-07-02 05:54:53 +02:00
if (!DataStoreUtils.hasAccount(this)) {
val signInIntent = Intent(INTENT_ACTION_TWITTER_LOGIN)
signInIntent.setClass(this, SignInActivity::class.java)
startActivity(signInIntent)
finish()
2016-12-23 02:26:52 +01:00
if (defaultAutoRefreshAskedKey !in kPreferences) {
2016-12-17 05:10:24 +01:00
// Assume first install
2016-12-23 02:26:52 +01:00
kPreferences[defaultAutoRefreshAskedKey] = false
2016-12-17 05:10:24 +01:00
}
2016-07-02 05:54:53 +02:00
return
} else {
notifyAccountsChanged()
}
supportRequestWindowFeature(AppCompatDelegate.FEATURE_ACTION_MODE_OVERLAY)
setContentView(R.layout.activity_home)
setSupportActionBar(toolbar)
drawerToggle = ActionBarDrawerToggle(this, homeMenu, R.string.open_accounts_dashboard,
R.string.close_accounts_dashboard)
pagerAdapter = SupportTabsAdapter(this, supportFragmentManager, mainTabs)
propertiesInitialized = true
2016-07-02 05:54:53 +02:00
ThemeUtils.setCompatContentViewOverlay(window, EmptyDrawable())
2017-06-25 17:01:33 +02:00
val refreshOnStart = preferences[refreshOnStartKey]
2016-07-02 05:54:53 +02:00
var tabDisplayOptionInt = Utils.getTabDisplayOptionInt(this)
2017-06-25 17:01:33 +02:00
ViewCompat.setOnApplyWindowInsetsListener(homeContent, this)
homeMenu.fitsSystemWindows = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ||
preferences[navbarStyleKey] != NavbarStyle.TRANSPARENT
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || !ViewCompat.getFitsSystemWindows(homeMenu)) {
2017-06-25 17:01:33 +02:00
ViewCompat.setOnApplyWindowInsetsListener(homeMenu, null)
}
mainPager.adapter = pagerAdapter
2016-07-02 05:54:53 +02:00
mainTabs.setViewPager(mainPager)
mainTabs.setOnPageChangeListener(this)
if (tabDisplayOptionInt == 0) {
tabDisplayOptionInt = TabPagerIndicator.DisplayOption.ICON
2016-07-02 05:54:53 +02:00
}
mainTabs.setTabDisplayOption(tabDisplayOptionInt)
mainTabs.setTabExpandEnabled(TabPagerIndicator.DisplayOption.LABEL !in tabDisplayOptionInt)
2016-12-23 02:26:52 +01:00
mainTabs.setDisplayBadge(preferences[unreadCountKey])
2016-07-02 05:54:53 +02:00
mainTabs.updateAppearance()
2016-12-23 02:26:52 +01:00
if (preferences[drawerToggleKey]) {
2016-07-02 05:54:53 +02:00
drawerToggleButton.visibility = View.VISIBLE
} else {
drawerToggleButton.visibility = View.GONE
}
2016-12-23 02:26:52 +01:00
if (preferences[fabVisibleKey]) {
actionsButton.visibility = View.VISIBLE
} else {
actionsButton.visibility = View.GONE
}
2017-06-25 17:01:33 +02:00
actionsButtonBottomMargin = (actionsButton.layoutParams as MarginLayoutParams).bottomMargin
homeContent.addOnLayoutChangeListener { _, _, top, _, _, _, oldTop, _, _ ->
2016-07-02 05:54:53 +02:00
if (top != oldTop) {
val fragment = leftDrawerFragment
if (fragment is AccountsDashboardFragment) {
fragment.setStatusBarHeight(top)
}
}
}
actionsButton.setOnClickListener(this)
actionsButton.setOnLongClickListener(this)
drawerToggleButton.setOnClickListener(this)
emptyTabHint.setOnClickListener(this)
setupSlidingMenu()
setupBars()
2017-08-30 05:59:57 +02:00
showPromotionOffer()
2016-07-02 05:54:53 +02:00
initUnreadCount()
setupHomeTabs()
updateActionsButton()
if (savedInstanceState == null) {
if (refreshOnStart) {
twitterWrapper.refreshAll(activatedAccountKeys)
}
if (intent.getBooleanExtra(EXTRA_OPEN_ACCOUNTS_DRAWER, false)) {
openAccountsDrawer()
}
}
2017-02-04 08:39:08 +01:00
val initialTabPosition = handleIntent(intent, savedInstanceState == null)
2016-07-02 05:54:53 +02:00
setTabPosition(initialTabPosition)
2016-12-23 02:26:52 +01:00
if (!showDrawerTutorial() && !kPreferences[defaultAutoRefreshAskedKey]) {
2016-12-17 05:10:24 +01:00
showAutoRefreshConfirm()
}
2016-07-02 05:54:53 +02:00
}
2017-02-16 07:50:25 +01:00
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState()
}
2016-07-02 05:54:53 +02:00
override fun onStart() {
super.onStart()
2016-12-06 02:26:53 +01:00
multiSelectHandler.dispatchOnStart()
AccountManager.get(this).addOnAccountsUpdatedListenerSafe(accountUpdatedListener, updateImmediately = false)
2016-07-02 05:54:53 +02:00
bus.register(this)
readStateManager.registerOnSharedPreferenceChangeListener(readStateChangeListener)
updateUnreadCount()
}
override fun onResume() {
super.onResume()
invalidateOptionsMenu()
updateActionsButton()
}
override fun onStop() {
2016-12-06 02:26:53 +01:00
multiSelectHandler.dispatchOnStop()
2016-07-02 05:54:53 +02:00
readStateManager.unregisterOnSharedPreferenceChangeListener(readStateChangeListener)
bus.unregister(this)
AccountManager.get(this).removeOnAccountsUpdatedListenerSafe(accountUpdatedListener)
2017-04-13 18:57:14 +02:00
preferences.edit().putInt(KEY_SAVED_TAB_POSITION, mainPager.currentItem).apply()
timelineSyncManager?.commit()
2016-07-02 05:54:53 +02:00
super.onStop()
}
2017-02-16 07:50:25 +01:00
override fun onDestroy() {
2017-03-12 14:27:55 +01:00
if (isFinishing) {
2017-04-14 13:28:09 +02:00
// Delete unused items in databases.
val context = applicationContext
task { DataStoreUtils.cleanDatabasesByItemLimit(context) }
}
2017-02-16 07:50:25 +01:00
super.onDestroy()
2016-07-02 05:54:53 +02:00
}
2017-09-03 12:05:56 +02:00
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Pass any configuration change to the drawer toggle
drawerToggle.onConfigurationChanged(newConfig)
}
2020-01-26 08:35:15 +01:00
override fun onAttachFragment(fragment: Fragment) {
2017-02-16 07:50:25 +01:00
super.onAttachFragment(fragment)
updateActionsButton()
2016-07-02 05:54:53 +02:00
}
override fun onClick(v: View) {
when (v) {
actionsButton -> {
triggerActionsClick()
}
emptyTabHint -> {
2017-03-13 06:35:11 +01:00
startActivityForResult(IntentUtils.settings("tabs"), REQUEST_SETTINGS)
2016-07-02 05:54:53 +02:00
}
drawerToggleButton -> {
if (homeMenu.isDrawerOpen(GravityCompat.START) || homeMenu.isDrawerOpen(GravityCompat.END)) {
homeMenu.closeDrawers()
} else {
homeMenu.openDrawer(GravityCompat.START)
}
}
}
}
override fun onLongClick(v: View): Boolean {
when (v) {
actionsButton -> {
Utils.showMenuItemToast(v, v.contentDescription, true)
return true
}
}
return false
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
//TODO handle secondary drawer
if (homeMenu.isDrawerOpen(GravityCompat.START)) {
homeMenu.closeDrawers()
}
updateActionsButton()
}
override fun onPageScrollStateChanged(state: Int) {
setControlBarVisibleAnimate(true)
}
override fun onSearchRequested(): Boolean {
startActivity(Intent(this, QuickSearchBarActivity::class.java))
return true
}
2017-06-26 08:48:05 +02:00
override fun getSystemWindowInsets(caller: Fragment, insets: Rect): Boolean {
if (caller === leftDrawerFragment) return super.getSystemWindowInsets(caller, insets)
2020-05-14 08:34:03 +02:00
if (mainTabs == null || homeContent == null || toolbar == null || !toolbar.isVisible) return false
2017-06-26 08:48:05 +02:00
val height = mainTabs.height
2020-05-12 09:20:12 +02:00
if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
if (height != 0) {
insets.top = height
} else {
insets.top = ThemeUtils.getActionBarHeight(this)
}
insets.bottom = systemWindowsInsets?.bottom ?: 0
2017-06-26 08:48:05 +02:00
} else {
2020-05-12 09:20:12 +02:00
if (height != 0) {
insets.bottom = height
} else {
insets.bottom = ThemeUtils.getActionBarHeight(this)
}
2017-06-26 08:48:05 +02:00
}
return true
}
2017-08-30 05:59:57 +02:00
@SuppressLint("RestrictedApi")
2017-06-25 17:01:33 +02:00
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
super.onApplyWindowInsets(v, insets)
2016-07-02 05:54:53 +02:00
val fragment = leftDrawerFragment
if (fragment is AccountsDashboardFragment) {
fragment.requestApplyInsets()
2016-07-02 05:54:53 +02:00
}
2017-06-25 17:01:33 +02:00
homeMenu.setChildInsets(insets.unwrapped, insets.systemWindowInsetTop > 0)
if (!ViewCompat.getFitsSystemWindows(homeMenu)) {
2017-06-25 17:01:33 +02:00
homeContent.setPadding(0, insets.systemWindowInsetTop, 0, 0)
}
2020-05-26 08:19:00 +02:00
(toolbar.layoutParams as? MarginLayoutParams)?.bottomMargin = insets.systemWindowInsetBottom
2017-06-25 17:01:33 +02:00
(actionsButton.layoutParams as? MarginLayoutParams)?.bottomMargin =
2020-05-26 08:19:00 +02:00
actionsButtonBottomMargin + if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
insets.systemWindowInsetBottom
} else {
0
}
2017-06-25 17:01:33 +02:00
return insets
2016-07-02 05:54:53 +02:00
}
override fun onNewIntent(intent: Intent) {
2020-05-31 08:02:32 +02:00
super.onNewIntent(intent)
2017-02-04 08:39:08 +01:00
val tabPosition = handleIntent(intent, false)
2016-07-02 05:54:53 +02:00
if (tabPosition >= 0) {
2017-02-04 11:42:14 +01:00
mainPager.currentItem = tabPosition.coerceInOr(0 until pagerAdapter.count, 0)
2016-07-02 05:54:53 +02:00
}
}
2017-02-16 07:50:25 +01:00
override fun setControlBarVisibleAnimate(visible: Boolean,
listener: ControlBarShowHideHelper.ControlBarAnimationListener?) {
controlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener)
}
2016-07-02 05:54:53 +02:00
2017-02-16 07:50:25 +01:00
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (drawerToggle.onOptionsItemSelected(item)) {
return true
}
when (item.itemId) {
android.R.id.home -> {
val fm = supportFragmentManager
val count = fm.backStackEntryCount
if (homeMenu.isDrawerOpen(GravityCompat.START) || homeMenu.isDrawerOpen(GravityCompat.END)) {
homeMenu.closeDrawers()
return true
} else if (count == 0) {
homeMenu.openDrawer(GravityCompat.START)
return true
}
return true
2016-07-02 05:54:53 +02:00
}
2017-02-16 07:50:25 +01:00
R.id.search -> {
openSearchView(selectedAccountToSearch)
return true
}
R.id.actions -> {
triggerActionsClick()
return true
}
}
return super.onOptionsItemSelected(item)
2016-07-02 05:54:53 +02:00
}
2017-02-16 07:50:25 +01:00
override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, keyCode: Int,
event: KeyEvent, metaState: Int): Boolean {
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event, metaState)) return true
var action = handler.getKeyAction(KeyboardShortcutConstants.CONTEXT_TAG_HOME, keyCode, event, metaState)
if (action != null) {
when (action) {
KeyboardShortcutConstants.ACTION_HOME_ACCOUNTS_DASHBOARD -> {
if (homeMenu.isDrawerOpen(GravityCompat.START)) {
homeMenu.closeDrawers()
} else {
homeMenu.openDrawer(GravityCompat.START)
setControlBarVisibleAnimate(true)
}
return true
}
}
}
action = handler.getKeyAction(KeyboardShortcutConstants.CONTEXT_TAG_NAVIGATION, keyCode, event, metaState)
if (action != null) {
when (action) {
KeyboardShortcutConstants.ACTION_NAVIGATION_PREVIOUS_TAB -> {
val previous = mainPager.currentItem - 1
if (previous < 0 && DrawerLayoutAccessor.findDrawerWithGravity(homeMenu, Gravity.START) != null) {
homeMenu.openDrawer(GravityCompat.START)
setControlBarVisibleAnimate(true)
} else if (previous < pagerAdapter.count) {
if (homeMenu.isDrawerOpen(GravityCompat.END)) {
homeMenu.closeDrawers()
} else {
mainPager.setCurrentItem(previous, true)
}
}
return true
}
KeyboardShortcutConstants.ACTION_NAVIGATION_NEXT_TAB -> {
val next = mainPager.currentItem + 1
if (next >= pagerAdapter.count && DrawerLayoutAccessor.findDrawerWithGravity(homeMenu, Gravity.END) != null) {
homeMenu.openDrawer(GravityCompat.END)
setControlBarVisibleAnimate(true)
} else if (next >= 0) {
if (homeMenu.isDrawerOpen(GravityCompat.START)) {
homeMenu.closeDrawers()
} else {
mainPager.setCurrentItem(next, true)
}
}
return true
}
}
}
return handler.handleKey(this, null, keyCode, event, metaState)
}
override fun isKeyboardShortcutHandled(handler: KeyboardShortcutsHandler, keyCode: Int,
event: KeyEvent, metaState: Int): Boolean {
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event, metaState)) return true
return super.isKeyboardShortcutHandled(handler, keyCode, event, metaState)
}
override fun handleKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler, keyCode: Int,
repeatCount: Int, event: KeyEvent, metaState: Int): Boolean {
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState))
return true
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState)
2016-07-02 05:54:53 +02:00
}
2017-09-03 12:05:56 +02:00
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
when (event.keyCode) {
2017-02-16 07:50:25 +01:00
KeyEvent.KEYCODE_MENU -> {
2017-09-03 12:05:56 +02:00
if (event.action != KeyEvent.ACTION_UP) return true
2017-02-16 07:50:25 +01:00
if (isDrawerOpen) {
homeMenu.closeDrawers()
} else {
homeMenu.openDrawer(GravityCompat.START)
}
return true
}
2017-09-03 12:05:56 +02:00
}
return super.dispatchKeyEvent(event)
}
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
when (keyCode) {
2017-02-16 07:50:25 +01:00
KeyEvent.KEYCODE_BACK -> {
if (isDrawerOpen) {
homeMenu.closeDrawers()
return true
}
}
}
return super.onKeyUp(keyCode, event)
}
override fun triggerRefresh(position: Int): Boolean {
val f = pagerAdapter.instantiateItem(mainPager, position)
if (f.activity == null || f.isDetached) return false
if (f !is RefreshScrollTopInterface) return false
return f.triggerRefresh()
}
2017-02-16 07:50:25 +01:00
fun notifyAccountsChanged() {
}
@Subscribe
fun notifyUnreadCountUpdated(event: UnreadCountUpdatedEvent) {
updateUnreadCount()
}
fun updateUnreadCount() {
if (mainTabs == null || updateUnreadCountTask != null && updateUnreadCountTask!!.status == AsyncTask.Status.RUNNING)
return
updateUnreadCountTask = UpdateUnreadCountTask(this, preferences, readStateManager, mainTabs,
2017-05-19 17:08:23 +02:00
pagerAdapter.tabs.toTypedArray()).apply { execute() }
2017-02-16 07:50:25 +01:00
mainTabs.setDisplayBadge(preferences.getBoolean(SharedPreferenceConstants.KEY_UNREAD_COUNT, true))
}
val tabs: List<SupportTabSpec>
get() = pagerAdapter.tabs
override var controlBarOffset: Float
get() {
2020-05-14 08:34:03 +02:00
if (mainTabs.columns > 1 || !toolbar.isVisible) {
val lp = actionsButton.layoutParams
val total: Float
total = if (lp is MarginLayoutParams) {
(lp.bottomMargin + actionsButton.height).toFloat()
} else {
actionsButton.height.toFloat()
}
return 1 - actionsButton.translationY / total
}
val totalHeight = controlBarHeight.toFloat()
2020-05-12 09:20:12 +02:00
return 1 + if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
toolbar.translationY
} else {
-toolbar.translationY
} / totalHeight
}
set(offset) {
2020-05-12 09:20:12 +02:00
if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
2020-05-14 08:34:03 +02:00
val translationY = if (mainTabs.columns > 1 || !toolbar.isVisible) {
2020-05-12 09:20:12 +02:00
0
} else {
(controlBarHeight * (offset - 1)).toInt()
}
toolbar.translationY = translationY.toFloat()
windowOverlay.translationY = translationY.toFloat()
val lp = actionsButton.layoutParams
if (lp is MarginLayoutParams) {
actionsButton.translationY = (lp.bottomMargin + actionsButton.height) * (1 - offset)
} else {
actionsButton.translationY = actionsButton.height * (1 - offset)
}
notifyControlBarOffsetChanged()
2016-07-02 05:54:53 +02:00
} else {
2020-05-26 08:19:00 +02:00
val layoutparams = toolbar.layoutParams
val toolbarMarginBottom = if (layoutparams is MarginLayoutParams) {
layoutparams.bottomMargin
} else {
0
}
2020-05-14 08:34:03 +02:00
val translationY = if (mainTabs.columns > 1 || !toolbar.isVisible) {
2020-05-12 09:20:12 +02:00
0
} else {
2020-05-26 08:19:00 +02:00
((toolbar.height + toolbarMarginBottom) * (offset - 1)).toInt()
2020-05-12 09:20:12 +02:00
}
toolbar.translationY = -translationY.toFloat()
windowOverlay.translationY = -translationY.toFloat()
val lp = actionsButton.layoutParams
if (lp is MarginLayoutParams) {
2020-05-26 08:19:00 +02:00
actionsButton.translationY = (lp.bottomMargin + toolbar.height + actionsButton.height + toolbarMarginBottom) * (1 - offset)
2020-05-12 09:20:12 +02:00
} else {
actionsButton.translationY = actionsButton.height * (1 - offset)
}
notifyControlBarOffsetChanged()
2016-07-02 05:54:53 +02:00
}
}
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
}
override fun onDrawerOpened(drawerView: View) {
}
override fun onDrawerClosed(drawerView: View) {
}
override fun onDrawerStateChanged(newState: Int) {
val fragment = leftDrawerFragment
if (newState == DrawerLayout.STATE_DRAGGING && fragment is AccountsDashboardFragment) {
2017-02-05 15:15:03 +01:00
fragment.loadAccounts()
2016-07-02 05:54:53 +02:00
}
}
override fun getDrawerToggleDelegate(): ActionBarDrawerToggle.Delegate? {
return homeDrawerToggleDelegate
}
fun closeAccountsDrawer() {
if (homeMenu == null) return
homeMenu.closeDrawers()
}
private fun openSearchView(account: AccountDetails?) {
selectedAccountToSearch = account
onSearchRequested()
}
2016-07-02 05:54:53 +02:00
private fun handleFragmentKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler,
2017-02-15 07:48:10 +01:00
keyCode: Int, repeatCount: Int,
event: KeyEvent, metaState: Int): Boolean {
2016-07-02 05:54:53 +02:00
val fragment = keyboardShortcutRecipient
if (fragment is KeyboardShortcutCallback) {
return fragment.handleKeyboardShortcutRepeat(handler, keyCode,
repeatCount, event, metaState)
}
return false
}
private fun handleFragmentKeyboardShortcutSingle(handler: KeyboardShortcutsHandler,
2017-02-15 07:48:10 +01:00
keyCode: Int, event: KeyEvent,
metaState: Int): Boolean {
2016-07-02 05:54:53 +02:00
val fragment = keyboardShortcutRecipient
if (fragment is KeyboardShortcutCallback) {
return fragment.handleKeyboardShortcutSingle(handler, keyCode,
event, metaState)
}
return false
}
private fun isFragmentKeyboardShortcutHandled(handler: KeyboardShortcutsHandler,
2017-02-15 07:48:10 +01:00
keyCode: Int, event: KeyEvent, metaState: Int): Boolean {
2016-07-02 05:54:53 +02:00
val fragment = keyboardShortcutRecipient
if (fragment is KeyboardShortcutCallback) {
return fragment.isKeyboardShortcutHandled(handler, keyCode,
event, metaState)
}
return false
}
2017-02-04 08:39:08 +01:00
private fun handleIntent(intent: Intent, handleExtraIntent: Boolean): Int {
2016-07-02 05:54:53 +02:00
// use package's class loader to prevent BadParcelException
intent.setExtrasClassLoader(classLoader)
// reset intent
setIntent(Intent(this, HomeActivity::class.java))
val action = intent.action
if (Intent.ACTION_SEARCH == action) {
val query = intent.getStringExtra(SearchManager.QUERY)
val appSearchData = intent.getBundleExtra(SearchManager.APP_DATA)
val accountKey = if (appSearchData != null && appSearchData.containsKey(EXTRA_ACCOUNT_KEY)) {
appSearchData.getParcelable(EXTRA_ACCOUNT_KEY)
2016-07-02 05:54:53 +02:00
} else {
Utils.getDefaultAccountKey(this)
2016-07-02 05:54:53 +02:00
}
if (query != null) {
IntentUtils.openSearch(this, accountKey, query)
}
2016-07-02 05:54:53 +02:00
return -1
}
val refreshOnStart = preferences.getBoolean(SharedPreferenceConstants.KEY_REFRESH_ON_START, false)
if (handleExtraIntent && refreshOnStart) {
twitterWrapper.refreshAll()
}
val uri = intent.data
@CustomTabType
val tabType = if (uri != null) Utils.matchTabType(uri) else null
var initialTab = -1
if (tabType != null) {
2017-02-17 11:42:39 +01:00
val accountKey = uri?.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY)?.let(UserKey::valueOf)
val adapter = pagerAdapter
2016-12-05 14:18:20 +01:00
for (i in 0 until adapter.count) {
2017-03-27 05:08:09 +02:00
val tab = adapter.get(i)
2016-12-01 08:55:38 +01:00
if (tabType == Tab.getTypeAlias(tab.type)) {
2016-07-07 05:42:08 +02:00
val args = tab.args
2017-04-12 14:58:08 +02:00
if (args != null && CustomTabUtils.hasAccountKey(this, args,
2016-07-02 05:54:53 +02:00
activatedAccountKeys, accountKey)) {
initialTab = i
break
}
}
}
if (initialTab == -1 && !handleExtraIntent) {
2016-07-02 05:54:53 +02:00
// Tab not found, open account specific page
when (tabType) {
CustomTabType.NOTIFICATIONS_TIMELINE -> {
IntentUtils.openInteractions(this, accountKey)
return -1
}
CustomTabType.DIRECT_MESSAGES -> {
IntentUtils.openDirectMessages(this, accountKey)
return -1
}
}
}
}
return initialTab
}
private fun initUnreadCount() {
for (i in 0 until mainTabs.count) {
2016-07-02 05:54:53 +02:00
mainTabs.setBadge(i, 0)
}
}
private fun openAccountsDrawer() {
if (homeMenu == null) return
homeMenu.openDrawer(GravityCompat.START)
}
2016-12-17 05:10:24 +01:00
private fun showDrawerTutorial(): Boolean {
2016-12-13 12:35:25 +01:00
if (preferences[drawerTutorialCompleted]) return false
val targetSize = resources.getDimensionPixelSize(R.dimen.element_size_mlarge)
val height = resources.displayMetrics.heightPixels
val listener: TapTargetView.Listener = object : TapTargetView.Listener() {
override fun onTargetClick(view: TapTargetView?) {
if (!homeMenu.isDrawerOpen(GravityCompat.START)) {
homeMenu.openDrawer(GravityCompat.START)
}
super.onTargetClick(view)
}
override fun onTargetDismissed(view: TapTargetView?, userInitiated: Boolean) {
preferences[drawerTutorialCompleted] = true
2016-12-17 05:10:24 +01:00
showAutoRefreshConfirm()
2016-12-13 12:35:25 +01:00
}
}
val target = Rect(0, 0, targetSize, targetSize)
target.offsetTo(0, height / 2 - targetSize / 2)
TapTargetView.showFor(this, TapTarget.forBounds(target,
getString(R.string.hint_accounts_dashboard_title),
getString(R.string.hint_accounts_dashboard_message))
.apply {
outerCircleColor(R.color.branding_color)
dimColor(android.R.color.black)
}, listener)
2016-07-02 05:54:53 +02:00
return true
}
2016-12-17 05:10:24 +01:00
private fun showAutoRefreshConfirm() {
if (isFinishing) return
executeAfterFragmentResumed { activity ->
val df = AutoRefreshConfirmDialogFragment()
df.show(activity.supportFragmentManager, "auto_refresh_confirm")
}
2016-12-17 05:10:24 +01:00
}
2016-07-02 05:54:53 +02:00
private fun setTabPosition(initialTab: Int) {
val rememberPosition = preferences.getBoolean(SharedPreferenceConstants.KEY_REMEMBER_POSITION, true)
if (initialTab >= 0) {
2017-02-04 11:42:14 +01:00
mainPager.currentItem = initialTab.coerceInOr(0 until pagerAdapter.count, 0)
2016-07-02 05:54:53 +02:00
} else if (rememberPosition) {
val position = preferences.getInt(SharedPreferenceConstants.KEY_SAVED_TAB_POSITION, 0)
2017-02-04 11:42:14 +01:00
mainPager.currentItem = position.coerceInOr(0 until pagerAdapter.count, 0)
2016-07-02 05:54:53 +02:00
}
}
private fun setupBars() {
val backgroundOption = currentThemeBackgroundOption
val isTransparent = ThemeUtils.isTransparentBackground(backgroundOption)
2017-03-21 03:33:27 +01:00
val actionBarAlpha = if (isTransparent) {
ThemeUtils.getActionBarAlpha(preferences[themeBackgroundAlphaKey])
} else {
0xFF
}
2016-07-02 05:54:53 +02:00
actionsButton.alpha = actionBarAlpha / 255f
}
private fun setupHomeTabs() {
pagerAdapter.clear()
2017-03-27 05:08:09 +02:00
pagerAdapter.addAll(CustomTabUtils.getHomeTabs(this))
val hasNoTab = pagerAdapter.count == 0
2016-07-02 05:54:53 +02:00
emptyTabHint.visibility = if (hasNoTab) View.VISIBLE else View.GONE
mainPager.visibility = if (hasNoTab) View.GONE else View.VISIBLE
if (pagerAdapter.count > 1 && hasMultiColumns()) {
mainPager.pageMargin = resources.getDimensionPixelOffset(R.dimen.home_page_margin)
2017-01-17 18:59:44 +01:00
mainPager.setPageMarginDrawable(ThemeUtils.getDrawableFromThemeAttribute(this, R.attr.dividerVertical))
2017-01-18 08:35:00 +01:00
pagerAdapter.hasMultipleColumns = true
pagerAdapter.preferredColumnWidth = when (preferences[multiColumnWidthKey]) {
"narrow" -> resources.getDimension(R.dimen.preferred_tab_column_width_narrow)
"wide" -> resources.getDimension(R.dimen.preferred_tab_column_width_wide)
else -> resources.getDimension(R.dimen.preferred_tab_column_width_normal)
}
2020-06-09 00:50:51 +02:00
mainTabs.columns = floor(1.0 / pagerAdapter.getPageWidth(0)).toInt()
} else {
mainPager.pageMargin = 0
mainPager.setPageMarginDrawable(null)
2017-01-18 08:35:00 +01:00
pagerAdapter.hasMultipleColumns = false
2017-01-23 15:26:29 +01:00
mainTabs.columns = 1
}
2020-05-14 08:34:03 +02:00
if (pagerAdapter.count == 1 && preferences[autoHideTabs]) {
toolbar.isVisible = false
actionsButton.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE)
}
} else if (preferences[tabPositionKey] == SharedPreferenceConstants.VALUE_TAB_POSITION_TOP) {
2020-05-12 09:20:12 +02:00
toolbar.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE)
}
actionsButton.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE)
}
} else {
toolbar.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE)
}
actionsButton.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.ABOVE, toolbar.id)
}
}
2016-07-02 05:54:53 +02:00
}
private fun setupSlidingMenu() {
homeMenu.setDrawerShadow(R.drawable.drawer_shadow_start, GravityCompat.START)
homeMenu.addDrawerListener(drawerToggle)
homeMenu.addDrawerListener(this)
homeMenu.setShouldDisableDecider(HomeDrawerLayout.ShouldDisableDecider { e ->
val fragment = leftDrawerFragment
if (fragment is AccountsDashboardFragment) {
2016-12-05 04:39:22 +01:00
return@ShouldDisableDecider fragment.shouldDisableDrawerSlide(e)
2016-07-02 05:54:53 +02:00
}
false
})
}
2017-08-30 05:59:57 +02:00
private fun showPromotionOffer() {
// Skip if app doesn't support extra features
if (!extraFeaturesService.isSupported()) return
// Skip if already bought enhanced features pack or have set promotions options
if (extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FEATURES_PACK)
2017-08-30 05:59:57 +02:00
|| promotionsEnabledKey in preferences) {
2016-07-02 05:54:53 +02:00
return
}
2017-09-16 18:35:21 +02:00
2017-08-30 05:59:57 +02:00
val intent = Intent(this, PremiumDashboardActivity::class.java)
2016-07-02 05:54:53 +02:00
val contentIntent = PendingIntent.getActivity(this, 0, intent, 0)
val builder = NotificationChannelSpec.appNotices.notificationBuilder(this)
2016-07-02 05:54:53 +02:00
builder.setAutoCancel(true)
2017-08-30 05:59:57 +02:00
builder.setSmallIcon(R.drawable.ic_stat_gift)
builder.setTicker(getString(R.string.message_ticker_promotions_reward))
builder.setContentTitle(getString(R.string.title_promotions_reward))
2017-09-16 18:35:21 +02:00
builder.setContentText(getString(R.string.message_ticker_promotions_reward))
2016-07-02 05:54:53 +02:00
builder.setContentIntent(contentIntent)
2017-09-16 18:35:21 +02:00
builder.setStyle(NotificationCompat.BigTextStyle(builder)
.setBigContentTitle(getString(R.string.title_promotions_reward))
.bigText(getString(R.string.message_promotions_reward)))
builder.addAction(R.drawable.ic_action_confirm, getString(R.string.action_enable),
PendingIntent.getBroadcast(this, 0, Intent(this,
NotificationReceiver::class.java).setAction(BROADCAST_PROMOTIONS_ACCEPTED)
.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID_PROMOTIONS_OFFER),
PendingIntent.FLAG_ONE_SHOT))
builder.addAction(R.drawable.ic_action_cancel, getString(R.string.action_no_thanks),
PendingIntent.getBroadcast(this, 0, Intent(this,
NotificationReceiver::class.java).setAction(BROADCAST_PROMOTIONS_DENIED)
.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID_PROMOTIONS_OFFER),
PendingIntent.FLAG_ONE_SHOT))
2017-08-30 05:59:57 +02:00
notificationManager.notify(NOTIFICATION_ID_PROMOTIONS_OFFER, builder.build())
2016-07-02 05:54:53 +02:00
}
private fun triggerActionsClick() {
val position = mainPager.currentItem
if (pagerAdapter.count == 0) return
2017-02-15 09:11:11 +01:00
val fragment = pagerAdapter.instantiateItem(mainPager, position) as? IFloatingActionButtonFragment
val handled = fragment?.onActionClick("home") ?: false
2017-02-15 07:55:18 +01:00
if (!handled) {
startActivity(Intent(INTENT_ACTION_COMPOSE))
2016-07-02 05:54:53 +02:00
}
}
private fun updateActionsButton() {
if (!propertiesInitialized) return
2017-02-16 07:50:25 +01:00
val fragment = run {
if (pagerAdapter.count == 0) return@run null
val position = mainPager.currentItem
val f = pagerAdapter.instantiateItem(mainPager, position) as? IFloatingActionButtonFragment
if (f is Fragment && (f.isDetached || f.host == null)) {
return@run null
}
return@run f
}
2017-02-15 07:48:10 +01:00
val info = fragment?.getActionInfo("home") ?: run {
actionsButton.setImageResource(R.drawable.ic_action_status_compose)
actionsButton.contentDescription = getString(R.string.action_compose)
return
2016-07-02 05:54:53 +02:00
}
2017-02-15 07:48:10 +01:00
actionsButton.setImageResource(info.icon)
actionsButton.contentDescription = info.title
2016-07-02 05:54:53 +02:00
}
private fun hasMultiColumns(): Boolean {
2017-04-17 04:44:58 +02:00
if (!DeviceUtils.isDeviceTablet(this) || !DeviceUtils.isScreenTablet(this)) return false
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
return preferences.getBoolean("multi_column_tabs_landscape", resources.getBoolean(R.bool.default_multi_column_tabs_land))
}
return preferences.getBoolean("multi_column_tabs_portrait", resources.getBoolean(R.bool.default_multi_column_tabs_port))
}
2016-12-12 14:19:02 +01:00
private class AccountUpdatedListener(private val activity: HomeActivity) : OnAccountsUpdateListener {
2016-07-02 05:54:53 +02:00
override fun onAccountsUpdated(accounts: Array<out Account>?) {
activity.notifyAccountsChanged()
activity.updateUnreadCount()
2016-07-02 05:54:53 +02:00
}
}
2017-03-02 02:08:54 +01:00
private class UpdateUnreadCountTask(
context: Context,
2016-12-24 15:05:15 +01:00
private val preferences: SharedPreferences,
2016-07-02 05:54:53 +02:00
private val readStateManager: ReadStateManager,
indicator: TabPagerIndicator,
2017-03-02 02:08:54 +01:00
private val tabs: Array<SupportTabSpec>
) : AsyncTask<Any, UpdateUnreadCountTask.TabBadge, SparseIntArray>() {
private val activatedKeys = DataStoreUtils.getActivatedAccountKeys(context)
private val contextRef = WeakReference(context)
private val indicatorRef = WeakReference(indicator)
2016-07-02 05:54:53 +02:00
override fun doInBackground(vararg params: Any): SparseIntArray {
val result = SparseIntArray()
val context = contextRef.get() ?: return result
2016-07-02 05:54:53 +02:00
tabs.forEachIndexed { i, spec ->
if (spec.type == null) {
publishProgress(TabBadge(i, -1))
return@forEachIndexed
}
when (spec.type) {
CustomTabType.HOME_TIMELINE -> {
2017-03-02 02:08:54 +01:00
val accountKeys = Utils.getAccountKeys(context, spec.args) ?: activatedKeys
2016-07-08 03:44:43 +02:00
val position = accountKeys.map {
val tag = Utils.getReadPositionTagWithAccount(ReadPositionTag.HOME_TIMELINE, it)
readStateManager.getPosition(tag)
}.fold(0L, Math::max)
2016-12-24 15:05:15 +01:00
val count = DataStoreUtils.getStatusesCount(context, preferences,
2017-04-28 15:44:45 +02:00
Statuses.CONTENT_URI, spec.args, Statuses.TIMESTAMP, position,
2017-09-10 17:32:12 +02:00
true, accountKeys, FilterScope.HOME)
2016-07-02 05:54:53 +02:00
result.put(i, count)
publishProgress(TabBadge(i, count))
}
CustomTabType.NOTIFICATIONS_TIMELINE -> {
2017-03-02 02:08:54 +01:00
val accountKeys = Utils.getAccountKeys(context, spec.args) ?: activatedKeys
2016-07-08 03:44:43 +02:00
val position = accountKeys.map {
val tag = Utils.getReadPositionTagWithAccount(ReadPositionTag.ACTIVITIES_ABOUT_ME, it)
readStateManager.getPosition(tag)
}.fold(0L, Math::max)
2017-09-13 11:52:09 +02:00
val count = DataStoreUtils.getInteractionsCount(context, preferences,
spec.args, accountKeys, position, Activities.TIMESTAMP,
FilterScope.INTERACTIONS)
2016-07-02 05:54:53 +02:00
result.put(i, count)
2017-04-23 16:00:54 +02:00
publishProgress(TabBadge(i, count))
2016-07-02 05:54:53 +02:00
}
2017-03-13 06:35:11 +01:00
CustomTabType.DIRECT_MESSAGES -> {
val accountKeys = Utils.getAccountKeys(context, spec.args) ?: activatedKeys
val projection = (Conversations.COLUMNS + Conversations.UNREAD_COUNT).map {
TwidereQueryBuilder.mapConversationsProjection(it)
}.toTypedArray()
2017-04-10 11:35:35 +02:00
val unreadHaving = Expression.greaterThan(Conversations.UNREAD_COUNT, 0)
val count = context.contentResolver.getUnreadMessagesEntriesCursorReference(projection,
accountKeys, extraHaving = unreadHaving)?.use { (cur) ->
return@use cur.count
2017-03-13 06:35:11 +01:00
} ?: -1
result.put(i, count)
2017-04-23 16:00:54 +02:00
publishProgress(TabBadge(i, count))
2017-03-13 06:35:11 +01:00
}
2016-07-02 05:54:53 +02:00
else -> {
publishProgress(TabBadge(i, -1))
}
}
}
return result
}
override fun onPostExecute(result: SparseIntArray) {
val indicator = indicatorRef.get() ?: return
2016-07-02 05:54:53 +02:00
indicator.clearBadge()
for (i in 0 until result.size()) {
2016-07-02 05:54:53 +02:00
indicator.setBadge(result.keyAt(i), result.valueAt(i))
}
}
override fun onProgressUpdate(vararg values: TabBadge) {
val indicator = indicatorRef.get() ?: return
2016-07-02 05:54:53 +02:00
for (value in values) {
indicator.setBadge(value.index, value.count)
}
}
internal class TabBadge(var index: Int, var count: Int)
}
2016-12-17 05:10:24 +01:00
class AutoRefreshConfirmDialogFragment : BaseDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireContext())
2016-12-17 05:10:24 +01:00
builder.setTitle(R.string.auto_refresh)
builder.setMessage(R.string.message_auto_refresh_confirm)
builder.setPositiveButton(android.R.string.ok) { _, _ ->
kPreferences[defaultAutoRefreshKey] = true
2016-12-17 05:10:24 +01:00
}
2017-09-16 18:35:21 +02:00
builder.setNegativeButton(R.string.action_no_thanks) { _, _ ->
kPreferences[defaultAutoRefreshKey] = false
2016-12-17 05:10:24 +01:00
}
2017-02-05 14:42:20 +01:00
val dialog = builder.create()
2017-06-19 15:45:41 +02:00
dialog.onShow { it.applyTheme() }
2017-02-05 14:42:20 +01:00
return dialog
2016-12-17 05:10:24 +01:00
}
2020-01-26 08:35:15 +01:00
override fun onDismiss(dialog: DialogInterface) {
2016-12-23 02:26:52 +01:00
kPreferences[defaultAutoRefreshAskedKey] = true
super.onDismiss(dialog)
}
2016-12-17 05:10:24 +01:00
}
2016-07-02 05:54:53 +02:00
companion object {
2020-01-26 08:35:15 +01:00
private val HOME_AS_UP_ATTRS = intArrayOf(android.R.attr.homeAsUpIndicator)
2016-07-02 05:54:53 +02:00
}
}