2020-04-15 18:57:53 +02:00
|
|
|
/* Copyright 2020 Tusky Contributors
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
2022-11-04 19:22:38 +01:00
|
|
|
import android.Manifest
|
2020-04-15 18:57:53 +02:00
|
|
|
import android.content.Context
|
|
|
|
import android.content.DialogInterface
|
|
|
|
import android.content.Intent
|
2022-11-04 19:22:38 +01:00
|
|
|
import android.content.pm.PackageManager
|
2020-04-15 18:57:53 +02:00
|
|
|
import android.content.res.ColorStateList
|
2021-12-05 19:12:52 +01:00
|
|
|
import android.graphics.Bitmap
|
2020-04-15 18:57:53 +02:00
|
|
|
import android.graphics.Color
|
2021-12-05 19:12:52 +01:00
|
|
|
import android.graphics.drawable.Animatable
|
|
|
|
import android.graphics.drawable.BitmapDrawable
|
2020-04-15 18:57:53 +02:00
|
|
|
import android.graphics.drawable.Drawable
|
|
|
|
import android.net.Uri
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.util.Log
|
|
|
|
import android.view.KeyEvent
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.View
|
|
|
|
import android.widget.ImageView
|
2022-11-04 19:22:38 +01:00
|
|
|
import androidx.activity.OnBackPressedCallback
|
2020-04-15 18:57:53 +02:00
|
|
|
import androidx.appcompat.app.AlertDialog
|
2020-06-18 11:04:53 +02:00
|
|
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
2022-11-04 19:22:38 +01:00
|
|
|
import androidx.core.app.ActivityCompat
|
|
|
|
import androidx.core.content.ContextCompat
|
2020-04-15 18:57:53 +02:00
|
|
|
import androidx.core.content.pm.ShortcutManagerCompat
|
2022-04-26 18:50:58 +02:00
|
|
|
import androidx.core.view.GravityCompat
|
2020-04-15 18:57:53 +02:00
|
|
|
import androidx.lifecycle.Lifecycle
|
2021-06-24 21:23:29 +02:00
|
|
|
import androidx.lifecycle.lifecycleScope
|
2020-04-15 18:57:53 +02:00
|
|
|
import androidx.preference.PreferenceManager
|
|
|
|
import androidx.viewpager2.widget.MarginPageTransformer
|
2022-05-30 20:03:40 +02:00
|
|
|
import at.connyduck.calladapter.networkresult.fold
|
2021-05-16 19:53:27 +02:00
|
|
|
import autodispose2.androidx.lifecycle.autoDispose
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.bumptech.glide.Glide
|
2020-11-22 19:03:11 +01:00
|
|
|
import com.bumptech.glide.RequestManager
|
2020-09-01 16:49:30 +02:00
|
|
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
|
|
|
import com.bumptech.glide.request.target.CustomTarget
|
|
|
|
import com.bumptech.glide.request.target.FixedSizeDrawable
|
|
|
|
import com.bumptech.glide.request.transition.Transition
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.google.android.material.tabs.TabLayout
|
|
|
|
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
|
|
|
import com.google.android.material.tabs.TabLayoutMediator
|
2021-06-28 22:04:34 +02:00
|
|
|
import com.keylesspalace.tusky.appstore.AnnouncementReadEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.CacheUpdater
|
|
|
|
import com.keylesspalace.tusky.appstore.Event
|
|
|
|
import com.keylesspalace.tusky.appstore.EventHub
|
|
|
|
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.ProfileEditedEvent
|
2022-01-11 19:55:17 +01:00
|
|
|
import com.keylesspalace.tusky.components.account.AccountActivity
|
2020-11-18 21:12:27 +01:00
|
|
|
import com.keylesspalace.tusky.components.announcements.AnnouncementsActivity
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
|
|
|
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.canHandleMimeType
|
2021-01-21 18:57:09 +01:00
|
|
|
import com.keylesspalace.tusky.components.drafts.DraftsActivity
|
2022-03-08 21:22:19 +01:00
|
|
|
import com.keylesspalace.tusky.components.login.LoginActivity
|
2020-05-12 18:46:49 +02:00
|
|
|
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
2022-05-17 19:32:09 +02:00
|
|
|
import com.keylesspalace.tusky.components.notifications.disableAllNotifications
|
|
|
|
import com.keylesspalace.tusky.components.notifications.enablePushNotificationsWithFallback
|
|
|
|
import com.keylesspalace.tusky.components.notifications.showMigrationNoticeIfNecessary
|
2020-09-02 12:27:51 +02:00
|
|
|
import com.keylesspalace.tusky.components.preference.PreferencesActivity
|
2022-03-20 20:21:42 +01:00
|
|
|
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusActivity
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.keylesspalace.tusky.components.search.SearchActivity
|
2021-03-07 19:05:51 +01:00
|
|
|
import com.keylesspalace.tusky.databinding.ActivityMainBinding
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.keylesspalace.tusky.db.AccountEntity
|
|
|
|
import com.keylesspalace.tusky.entity.Account
|
2022-11-07 20:04:07 +01:00
|
|
|
import com.keylesspalace.tusky.entity.Notification
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.keylesspalace.tusky.interfaces.AccountSelectionListener
|
|
|
|
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
|
|
|
import com.keylesspalace.tusky.interfaces.ReselectableFragment
|
|
|
|
import com.keylesspalace.tusky.pager.MainPagerAdapter
|
2020-08-16 10:01:51 +02:00
|
|
|
import com.keylesspalace.tusky.settings.PrefKeys
|
2022-06-20 16:45:54 +02:00
|
|
|
import com.keylesspalace.tusky.usecase.LogoutUsecase
|
2021-06-28 22:04:34 +02:00
|
|
|
import com.keylesspalace.tusky.util.ThemeUtils
|
|
|
|
import com.keylesspalace.tusky.util.deleteStaleCachedMedia
|
|
|
|
import com.keylesspalace.tusky.util.emojify
|
|
|
|
import com.keylesspalace.tusky.util.hide
|
2022-06-20 16:45:54 +02:00
|
|
|
import com.keylesspalace.tusky.util.show
|
2021-06-28 22:04:34 +02:00
|
|
|
import com.keylesspalace.tusky.util.updateShortcut
|
|
|
|
import com.keylesspalace.tusky.util.viewBinding
|
|
|
|
import com.keylesspalace.tusky.util.visible
|
2020-06-18 11:04:53 +02:00
|
|
|
import com.mikepenz.iconics.IconicsDrawable
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
2020-06-18 11:04:53 +02:00
|
|
|
import com.mikepenz.iconics.utils.colorInt
|
|
|
|
import com.mikepenz.iconics.utils.sizeDp
|
2020-11-18 21:12:27 +01:00
|
|
|
import com.mikepenz.materialdrawer.holder.BadgeStyle
|
|
|
|
import com.mikepenz.materialdrawer.holder.ColorHolder
|
|
|
|
import com.mikepenz.materialdrawer.holder.StringHolder
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.mikepenz.materialdrawer.iconics.iconicsIcon
|
2021-06-28 22:04:34 +02:00
|
|
|
import com.mikepenz.materialdrawer.model.AbstractDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.DividerDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.IProfile
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.descriptionRes
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.descriptionText
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.iconRes
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.iconUrl
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.nameRes
|
|
|
|
import com.mikepenz.materialdrawer.model.interfaces.nameText
|
|
|
|
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
|
|
|
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
|
|
|
import com.mikepenz.materialdrawer.util.addItems
|
|
|
|
import com.mikepenz.materialdrawer.util.addItemsAtPosition
|
|
|
|
import com.mikepenz.materialdrawer.util.updateBadge
|
2020-04-15 18:57:53 +02:00
|
|
|
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
|
|
|
import dagger.android.DispatchingAndroidInjector
|
|
|
|
import dagger.android.HasAndroidInjector
|
2022-04-26 18:50:58 +02:00
|
|
|
import de.c1710.filemojicompat_ui.helpers.EMOJI_PREFERENCE
|
2021-05-16 19:53:27 +02:00
|
|
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|
|
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
2021-06-24 21:23:29 +02:00
|
|
|
import kotlinx.coroutines.launch
|
2020-04-15 18:57:53 +02:00
|
|
|
import javax.inject.Inject
|
|
|
|
|
|
|
|
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
|
|
|
@Inject
|
|
|
|
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
lateinit var eventHub: EventHub
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
lateinit var cacheUpdater: CacheUpdater
|
|
|
|
|
|
|
|
@Inject
|
2022-06-20 16:45:54 +02:00
|
|
|
lateinit var logoutUsecase: LogoutUsecase
|
2021-02-07 16:40:09 +01:00
|
|
|
|
2021-03-07 19:05:51 +01:00
|
|
|
private val binding by viewBinding(ActivityMainBinding::inflate)
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
private lateinit var header: AccountHeaderView
|
|
|
|
|
|
|
|
private var notificationTabPosition = 0
|
2020-06-18 11:04:53 +02:00
|
|
|
private var onTabSelectedListener: OnTabSelectedListener? = null
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2020-11-18 21:12:27 +01:00
|
|
|
private var unreadAnnouncementsCount = 0
|
|
|
|
|
2020-08-16 10:01:51 +02:00
|
|
|
private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
|
|
|
|
|
2020-11-22 19:03:11 +01:00
|
|
|
private lateinit var glide: RequestManager
|
|
|
|
|
2021-04-10 20:30:44 +02:00
|
|
|
private var accountLocked: Boolean = false
|
|
|
|
|
2022-04-26 18:50:58 +02:00
|
|
|
// We need to know if the emoji pack has been changed
|
|
|
|
private var selectedEmojiPack: String? = null
|
2020-04-15 18:57:53 +02:00
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
2020-11-25 19:41:57 +01:00
|
|
|
|
|
|
|
val activeAccount = accountManager.activeAccount
|
2021-05-22 19:24:40 +02:00
|
|
|
?: return // will be redirected to LoginActivity by BaseActivity
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
var showNotificationTab = false
|
|
|
|
if (intent != null) {
|
|
|
|
/** there are two possibilities the accountId can be passed to MainActivity:
|
|
|
|
* - from our code as long 'account_id'
|
|
|
|
* - from share shortcuts as String 'android.intent.extra.shortcut.ID'
|
|
|
|
*/
|
|
|
|
var accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1)
|
|
|
|
if (accountId == -1L) {
|
|
|
|
val accountIdString = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID)
|
|
|
|
if (accountIdString != null) {
|
|
|
|
accountId = accountIdString.toLong()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val accountRequested = accountId != -1L
|
2020-12-13 16:32:04 +01:00
|
|
|
if (accountRequested && accountId != activeAccount.id) {
|
|
|
|
accountManager.setActiveAccount(accountId)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
2022-08-16 20:08:03 +02:00
|
|
|
|
|
|
|
val openDrafts = intent.getBooleanExtra(OPEN_DRAFTS, false)
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
if (canHandleMimeType(intent.type)) {
|
|
|
|
// Sharing to Tusky from an external app
|
|
|
|
if (accountRequested) {
|
|
|
|
// The correct account is already active
|
|
|
|
forwardShare(intent)
|
|
|
|
} else {
|
|
|
|
// No account was provided, show the chooser
|
2021-06-28 22:04:34 +02:00
|
|
|
showAccountChooserDialog(
|
|
|
|
getString(R.string.action_share_as), true,
|
|
|
|
object : AccountSelectionListener {
|
|
|
|
override fun onAccountSelected(account: AccountEntity) {
|
|
|
|
val requestedId = account.id
|
|
|
|
if (requestedId == activeAccount.id) {
|
|
|
|
// The correct account is already active
|
|
|
|
forwardShare(intent)
|
|
|
|
} else {
|
|
|
|
// A different account was requested, restart the activity
|
|
|
|
intent.putExtra(NotificationHelper.ACCOUNT_ID, requestedId)
|
|
|
|
changeAccount(requestedId, intent)
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
2022-08-16 20:08:03 +02:00
|
|
|
} else if (openDrafts) {
|
|
|
|
val intent = DraftsActivity.newIntent(this)
|
|
|
|
startActivity(intent)
|
2021-03-07 19:29:45 +01:00
|
|
|
} else if (accountRequested && savedInstanceState == null) {
|
2022-11-07 20:04:07 +01:00
|
|
|
// user clicked a notification, show follow requests for type FOLLOW_REQUEST,
|
|
|
|
// otherwise show notification tab
|
|
|
|
if (intent.getStringExtra(NotificationHelper.TYPE) == Notification.Type.FOLLOW_REQUEST.name) {
|
|
|
|
val intent = AccountListActivity.newIntent(this, AccountListActivity.Type.FOLLOW_REQUESTS, accountLocked = true)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
} else {
|
|
|
|
showNotificationTab = true
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
|
2021-03-07 19:05:51 +01:00
|
|
|
setContentView(binding.root)
|
2020-11-22 19:03:11 +01:00
|
|
|
|
|
|
|
glide = Glide.with(this)
|
|
|
|
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.composeButton.setOnClickListener {
|
2020-04-15 18:57:53 +02:00
|
|
|
val composeIntent = Intent(applicationContext, ComposeActivity::class.java)
|
|
|
|
startActivity(composeIntent)
|
|
|
|
}
|
2020-06-18 11:04:53 +02:00
|
|
|
|
2020-08-16 10:01:51 +02:00
|
|
|
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainToolbar.visible(!hideTopToolbar)
|
2020-08-16 10:01:51 +02:00
|
|
|
|
2020-11-25 19:41:57 +01:00
|
|
|
loadDrawerAvatar(activeAccount.profilePictureUrl, true)
|
2020-09-01 16:49:30 +02:00
|
|
|
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainToolbar.menu.add(R.string.action_search).apply {
|
2020-06-18 11:04:53 +02:00
|
|
|
setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
|
|
|
icon = IconicsDrawable(this@MainActivity, GoogleMaterial.Icon.gmd_search).apply {
|
|
|
|
sizeDp = 20
|
|
|
|
colorInt = ThemeUtils.getColor(this@MainActivity, android.R.attr.textColorPrimary)
|
|
|
|
}
|
|
|
|
setOnMenuItemClickListener {
|
|
|
|
startActivity(SearchActivity.getIntent(this@MainActivity))
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-16 10:01:51 +02:00
|
|
|
setupDrawer(savedInstanceState, addSearchButton = hideTopToolbar)
|
2020-04-15 18:57:53 +02:00
|
|
|
|
|
|
|
/* Fetch user info while we're doing other things. This has to be done after setting up the
|
|
|
|
* drawer, though, because its callback touches the header in the drawer. */
|
|
|
|
fetchUserInfo()
|
|
|
|
|
2020-11-18 21:12:27 +01:00
|
|
|
fetchAnnouncements()
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
setupTabs(showNotificationTab)
|
|
|
|
|
|
|
|
eventHub.events
|
2021-06-24 21:23:29 +02:00
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.autoDispose(this, Lifecycle.Event.ON_DESTROY)
|
|
|
|
.subscribe { event: Event? ->
|
|
|
|
when (event) {
|
|
|
|
is ProfileEditedEvent -> onFetchUserInfoSuccess(event.newProfileData)
|
|
|
|
is MainTabsChangedEvent -> setupTabs(false)
|
|
|
|
is AnnouncementReadEvent -> {
|
|
|
|
unreadAnnouncementsCount--
|
|
|
|
updateAnnouncementsBadge()
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
}
|
2021-06-24 21:23:29 +02:00
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2020-11-23 20:05:48 +01:00
|
|
|
Schedulers.io().scheduleDirect {
|
|
|
|
// Flush old media that was cached for sharing
|
|
|
|
deleteStaleCachedMedia(applicationContext.getExternalFilesDir("Tusky"))
|
|
|
|
}
|
2022-04-26 18:50:58 +02:00
|
|
|
|
|
|
|
selectedEmojiPack = preferences.getString(EMOJI_PREFERENCE, "")
|
2022-11-04 19:22:38 +01:00
|
|
|
|
|
|
|
onBackPressedDispatcher.addCallback(
|
|
|
|
this,
|
|
|
|
object : OnBackPressedCallback(true) {
|
|
|
|
override fun handleOnBackPressed() {
|
|
|
|
when {
|
|
|
|
binding.mainDrawerLayout.isOpen -> {
|
|
|
|
binding.mainDrawerLayout.close()
|
|
|
|
}
|
|
|
|
binding.viewPager.currentItem != 0 -> {
|
|
|
|
binding.viewPager.currentItem = 0
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
|
|
|
ActivityCompat.requestPermissions(
|
|
|
|
this,
|
|
|
|
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
|
|
|
|
1
|
|
|
|
)
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
super.onResume()
|
|
|
|
NotificationHelper.clearNotificationsForActiveAccount(this, accountManager)
|
2022-04-26 18:50:58 +02:00
|
|
|
val currentEmojiPack = preferences.getString(EMOJI_PREFERENCE, "")
|
|
|
|
if (currentEmojiPack != selectedEmojiPack) {
|
|
|
|
Log.d(
|
|
|
|
TAG,
|
|
|
|
"onResume: EmojiPack has been changed from %s to %s"
|
|
|
|
.format(selectedEmojiPack, currentEmojiPack)
|
|
|
|
)
|
|
|
|
selectedEmojiPack = currentEmojiPack
|
|
|
|
recreate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onStart() {
|
|
|
|
super.onStart()
|
|
|
|
// For some reason the navigation drawer is opened when the activity is recreated
|
|
|
|
if (binding.mainDrawerLayout.isOpen) {
|
|
|
|
binding.mainDrawerLayout.closeDrawer(GravityCompat.START, false)
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
|
|
|
when (keyCode) {
|
|
|
|
KeyEvent.KEYCODE_MENU -> {
|
2021-03-07 19:05:51 +01:00
|
|
|
if (binding.mainDrawerLayout.isOpen) {
|
|
|
|
binding.mainDrawerLayout.close()
|
2020-04-15 18:57:53 +02:00
|
|
|
} else {
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainDrawerLayout.open()
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
KeyEvent.KEYCODE_SEARCH -> {
|
|
|
|
startActivityWithSlideInAnimation(SearchActivity.getIntent(this))
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (event.isCtrlPressed || event.isShiftPressed) {
|
|
|
|
// FIXME: blackberry keyONE raises SHIFT key event even CTRL IS PRESSED
|
|
|
|
when (keyCode) {
|
|
|
|
KeyEvent.KEYCODE_N -> {
|
|
|
|
|
|
|
|
// open compose activity by pressing SHIFT + N (or CTRL + N)
|
|
|
|
val composeIntent = Intent(applicationContext, ComposeActivity::class.java)
|
|
|
|
startActivity(composeIntent)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.onKeyDown(keyCode, event)
|
|
|
|
}
|
|
|
|
|
|
|
|
public override fun onPostCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onPostCreate(savedInstanceState)
|
|
|
|
|
|
|
|
if (intent != null) {
|
2022-02-25 18:55:58 +01:00
|
|
|
val redirectUrl = intent.getStringExtra(REDIRECT_URL)
|
|
|
|
if (redirectUrl != null) {
|
|
|
|
viewUrl(redirectUrl, PostLookupFallbackBehavior.DISPLAY_ERROR)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun forwardShare(intent: Intent) {
|
|
|
|
val composeIntent = Intent(this, ComposeActivity::class.java)
|
|
|
|
composeIntent.action = intent.action
|
|
|
|
composeIntent.type = intent.type
|
|
|
|
composeIntent.putExtras(intent)
|
|
|
|
composeIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
|
|
|
startActivity(composeIntent)
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
|
2020-08-16 10:01:51 +02:00
|
|
|
private fun setupDrawer(savedInstanceState: Bundle?, addSearchButton: Boolean) {
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
val drawerOpenClickListener = View.OnClickListener { binding.mainDrawerLayout.open() }
|
|
|
|
|
|
|
|
binding.mainToolbar.setNavigationOnClickListener(drawerOpenClickListener)
|
|
|
|
binding.topNavAvatar.setOnClickListener(drawerOpenClickListener)
|
|
|
|
binding.bottomNavAvatar.setOnClickListener(drawerOpenClickListener)
|
2020-04-15 18:57:53 +02:00
|
|
|
|
|
|
|
header = AccountHeaderView(this).apply {
|
|
|
|
headerBackgroundScaleType = ImageView.ScaleType.CENTER_CROP
|
|
|
|
currentHiddenInList = true
|
|
|
|
onAccountHeaderListener = { _: View?, profile: IProfile, current: Boolean -> handleProfileClick(profile, current) }
|
2021-06-28 22:04:34 +02:00
|
|
|
addProfile(
|
|
|
|
ProfileSettingDrawerItem().apply {
|
|
|
|
identifier = DRAWER_ITEM_ADD_ACCOUNT
|
|
|
|
nameRes = R.string.add_account_name
|
|
|
|
descriptionRes = R.string.add_account_description
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_add
|
|
|
|
},
|
|
|
|
0
|
|
|
|
)
|
2021-03-07 19:05:51 +01:00
|
|
|
attachToSliderView(binding.mainDrawer)
|
2020-04-15 18:57:53 +02:00
|
|
|
dividerBelowHeader = false
|
|
|
|
closeDrawerOnProfileListClick = true
|
|
|
|
}
|
|
|
|
|
2022-08-04 16:48:26 +02:00
|
|
|
header.accountHeaderBackground.setColorFilter(getColor(R.color.headerBackgroundFilter))
|
2020-04-15 18:57:53 +02:00
|
|
|
header.accountHeaderBackground.setBackgroundColor(ThemeUtils.getColor(this, R.attr.colorBackgroundAccent))
|
2020-08-16 10:01:51 +02:00
|
|
|
val animateAvatars = preferences.getBoolean("animateGifAvatars", false)
|
2020-04-15 18:57:53 +02:00
|
|
|
|
|
|
|
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
|
|
|
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
|
|
|
|
if (animateAvatars) {
|
2020-11-22 19:03:11 +01:00
|
|
|
glide.load(uri)
|
2021-06-24 21:23:29 +02:00
|
|
|
.placeholder(placeholder)
|
|
|
|
.into(imageView)
|
2020-04-15 18:57:53 +02:00
|
|
|
} else {
|
2020-11-22 19:03:11 +01:00
|
|
|
glide.asBitmap()
|
2021-06-24 21:23:29 +02:00
|
|
|
.load(uri)
|
|
|
|
.placeholder(placeholder)
|
|
|
|
.into(imageView)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun cancel(imageView: ImageView) {
|
2020-11-22 19:03:11 +01:00
|
|
|
glide.clear(imageView)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun placeholder(ctx: Context, tag: String?): Drawable {
|
|
|
|
if (tag == DrawerImageLoader.Tags.PROFILE.name || tag == DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name) {
|
|
|
|
return ctx.getDrawable(R.drawable.avatar_default)!!
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.placeholder(ctx, tag)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainDrawer.apply {
|
2020-04-15 18:57:53 +02:00
|
|
|
tintStatusBar = true
|
|
|
|
addItems(
|
2021-06-24 21:23:29 +02:00
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_edit_profile
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_person
|
|
|
|
onClick = {
|
|
|
|
val intent = Intent(context, EditProfileActivity::class.java)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_view_favourites
|
|
|
|
isSelectable = false
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_star
|
|
|
|
onClick = {
|
|
|
|
val intent = StatusListActivity.newFavouritesIntent(context)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_view_bookmarks
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_bookmark
|
|
|
|
onClick = {
|
|
|
|
val intent = StatusListActivity.newBookmarksIntent(context)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
2021-06-24 21:23:29 +02:00
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_view_follow_requests
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_person_add
|
|
|
|
onClick = {
|
|
|
|
val intent = AccountListActivity.newIntent(context, AccountListActivity.Type.FOLLOW_REQUESTS, accountLocked = accountLocked)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_lists
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_list
|
|
|
|
onClick = {
|
|
|
|
startActivityWithSlideInAnimation(ListsActivity.newIntent(context))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_access_drafts
|
|
|
|
iconRes = R.drawable.ic_notebook
|
|
|
|
onClick = {
|
|
|
|
val intent = DraftsActivity.newIntent(context)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
2022-03-20 20:21:42 +01:00
|
|
|
nameRes = R.string.action_access_scheduled_posts
|
2021-06-24 21:23:29 +02:00
|
|
|
iconRes = R.drawable.ic_access_time
|
|
|
|
onClick = {
|
2022-03-20 20:21:42 +01:00
|
|
|
startActivityWithSlideInAnimation(ScheduledStatusActivity.newIntent(context))
|
2021-06-24 21:23:29 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
primaryDrawerItem {
|
|
|
|
identifier = DRAWER_ITEM_ANNOUNCEMENTS
|
|
|
|
nameRes = R.string.title_announcements
|
|
|
|
iconRes = R.drawable.ic_bullhorn_24dp
|
|
|
|
onClick = {
|
|
|
|
startActivityWithSlideInAnimation(AnnouncementsActivity.newIntent(context))
|
|
|
|
}
|
|
|
|
badgeStyle = BadgeStyle().apply {
|
|
|
|
textColor = ColorHolder.fromColor(ThemeUtils.getColor(this@MainActivity, R.attr.colorOnPrimary))
|
|
|
|
color = ColorHolder.fromColor(ThemeUtils.getColor(this@MainActivity, R.attr.colorPrimary))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
DividerDrawerItem(),
|
|
|
|
secondaryDrawerItem {
|
|
|
|
nameRes = R.string.action_view_account_preferences
|
|
|
|
iconRes = R.drawable.ic_account_settings
|
|
|
|
onClick = {
|
|
|
|
val intent = PreferencesActivity.newIntent(context, PreferencesActivity.ACCOUNT_PREFERENCES)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
secondaryDrawerItem {
|
|
|
|
nameRes = R.string.action_view_preferences
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_settings
|
|
|
|
onClick = {
|
|
|
|
val intent = PreferencesActivity.newIntent(context, PreferencesActivity.GENERAL_PREFERENCES)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
secondaryDrawerItem {
|
|
|
|
nameRes = R.string.about_title_activity
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_info
|
|
|
|
onClick = {
|
|
|
|
val intent = Intent(context, AboutActivity::class.java)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
secondaryDrawerItem {
|
|
|
|
nameRes = R.string.action_logout
|
|
|
|
iconRes = R.drawable.ic_logout
|
|
|
|
onClick = ::logout
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
)
|
2020-08-16 10:01:51 +02:00
|
|
|
|
2020-09-20 18:43:28 +02:00
|
|
|
if (addSearchButton) {
|
2021-06-28 22:04:34 +02:00
|
|
|
binding.mainDrawer.addItemsAtPosition(
|
|
|
|
4,
|
2021-06-24 21:23:29 +02:00
|
|
|
primaryDrawerItem {
|
|
|
|
nameRes = R.string.action_search
|
|
|
|
iconicsIcon = GoogleMaterial.Icon.gmd_search
|
|
|
|
onClick = {
|
|
|
|
startActivityWithSlideInAnimation(SearchActivity.getIntent(context))
|
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
}
|
|
|
|
)
|
2020-08-16 10:01:51 +02:00
|
|
|
}
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
setSavedInstance(savedInstanceState)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BuildConfig.DEBUG) {
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainDrawer.addItems(
|
2021-06-24 21:23:29 +02:00
|
|
|
secondaryDrawerItem {
|
|
|
|
nameText = "debug"
|
|
|
|
isEnabled = false
|
|
|
|
textColor = ColorStateList.valueOf(Color.GREEN)
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
2021-03-07 19:05:51 +01:00
|
|
|
super.onSaveInstanceState(binding.mainDrawer.saveInstanceState(outState))
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun setupTabs(selectNotificationTab: Boolean) {
|
2020-06-18 11:04:53 +02:00
|
|
|
|
2020-09-20 18:43:28 +02:00
|
|
|
val activeTabLayout = if (preferences.getString("mainNavPosition", "top") == "bottom") {
|
2020-06-18 11:04:53 +02:00
|
|
|
val actionBarSize = ThemeUtils.getDimension(this, R.attr.actionBarSize)
|
|
|
|
val fabMargin = resources.getDimensionPixelSize(R.dimen.fabMargin)
|
2021-03-07 19:05:51 +01:00
|
|
|
(binding.composeButton.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = actionBarSize + fabMargin
|
2022-12-03 12:16:54 +01:00
|
|
|
binding.topNav.hide()
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.bottomTabLayout
|
2020-06-18 11:04:53 +02:00
|
|
|
} else {
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.bottomNav.hide()
|
|
|
|
(binding.viewPager.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 0
|
|
|
|
(binding.composeButton.layoutParams as CoordinatorLayout.LayoutParams).anchorId = R.id.viewPager
|
|
|
|
binding.tabLayout
|
2020-06-18 11:04:53 +02:00
|
|
|
}
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
val tabs = accountManager.activeAccount!!.tabPreferences
|
2020-06-18 11:04:53 +02:00
|
|
|
|
|
|
|
val adapter = MainPagerAdapter(tabs, this)
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.viewPager.adapter = adapter
|
|
|
|
TabLayoutMediator(activeTabLayout, binding.viewPager) { _: TabLayout.Tab?, _: Int -> }.attach()
|
2020-06-18 11:04:53 +02:00
|
|
|
activeTabLayout.removeAllTabs()
|
2020-04-15 18:57:53 +02:00
|
|
|
for (i in tabs.indices) {
|
2020-06-18 11:04:53 +02:00
|
|
|
val tab = activeTabLayout.newTab()
|
2021-06-24 21:23:29 +02:00
|
|
|
.setIcon(tabs[i].icon)
|
2020-04-15 18:57:53 +02:00
|
|
|
if (tabs[i].id == LIST) {
|
|
|
|
tab.contentDescription = tabs[i].arguments[1]
|
|
|
|
} else {
|
|
|
|
tab.setContentDescription(tabs[i].text)
|
|
|
|
}
|
2020-06-18 11:04:53 +02:00
|
|
|
activeTabLayout.addTab(tab)
|
|
|
|
|
2020-04-15 18:57:53 +02:00
|
|
|
if (tabs[i].id == NOTIFICATIONS) {
|
|
|
|
notificationTabPosition = i
|
|
|
|
if (selectNotificationTab) {
|
|
|
|
tab.select()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-18 11:04:53 +02:00
|
|
|
|
|
|
|
val pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.viewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
2020-06-18 11:04:53 +02:00
|
|
|
|
2022-12-01 19:51:13 +01:00
|
|
|
val enableSwipeForTabs = preferences.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true)
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.viewPager.isUserInputEnabled = enableSwipeForTabs
|
2020-06-18 11:04:53 +02:00
|
|
|
|
|
|
|
onTabSelectedListener?.let {
|
|
|
|
activeTabLayout.removeOnTabSelectedListener(it)
|
|
|
|
}
|
|
|
|
|
|
|
|
onTabSelectedListener = object : OnTabSelectedListener {
|
|
|
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
|
|
|
if (tab.position == notificationTabPosition) {
|
|
|
|
NotificationHelper.clearNotificationsForActiveAccount(this@MainActivity, accountManager)
|
|
|
|
}
|
|
|
|
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainToolbar.title = tabs[tab.position].title(this@MainActivity)
|
2020-06-18 11:04:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
|
|
|
|
|
|
|
override fun onTabReselected(tab: TabLayout.Tab) {
|
|
|
|
val fragment = adapter.getFragment(tab.position)
|
|
|
|
if (fragment is ReselectableFragment) {
|
|
|
|
(fragment as ReselectableFragment).onReselect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.also {
|
|
|
|
activeTabLayout.addOnTabSelectedListener(it)
|
|
|
|
}
|
|
|
|
|
2020-06-21 19:52:27 +02:00
|
|
|
val activeTabPosition = if (selectNotificationTab) notificationTabPosition else 0
|
2021-03-07 19:05:51 +01:00
|
|
|
binding.mainToolbar.title = tabs[activeTabPosition].title(this@MainActivity)
|
|
|
|
binding.mainToolbar.setOnClickListener {
|
2021-01-15 21:23:02 +01:00
|
|
|
(adapter.getFragment(activeTabLayout.selectedTabPosition) as? ReselectableFragment)?.onReselect()
|
|
|
|
}
|
2022-05-12 18:21:33 +02:00
|
|
|
|
|
|
|
updateProfiles()
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun handleProfileClick(profile: IProfile, current: Boolean): Boolean {
|
|
|
|
val activeAccount = accountManager.activeAccount
|
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
// open profile when active image was clicked
|
2020-04-15 18:57:53 +02:00
|
|
|
if (current && activeAccount != null) {
|
|
|
|
val intent = AccountActivity.getIntent(this, activeAccount.accountId)
|
|
|
|
startActivityWithSlideInAnimation(intent)
|
|
|
|
return false
|
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
// open LoginActivity to add new account
|
2020-04-15 18:57:53 +02:00
|
|
|
if (profile.identifier == DRAWER_ITEM_ADD_ACCOUNT) {
|
2022-05-17 19:32:09 +02:00
|
|
|
startActivityWithSlideInAnimation(LoginActivity.getIntent(this, LoginActivity.MODE_ADDITIONAL_LOGIN))
|
2020-04-15 18:57:53 +02:00
|
|
|
return false
|
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
// change Account
|
2020-04-15 18:57:53 +02:00
|
|
|
changeAccount(profile.identifier, null)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun changeAccount(newSelectedId: Long, forward: Intent?) {
|
|
|
|
cacheUpdater.stop()
|
|
|
|
accountManager.setActiveAccount(newSelectedId)
|
|
|
|
val intent = Intent(this, MainActivity::class.java)
|
|
|
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
|
|
|
if (forward != null) {
|
|
|
|
intent.type = forward.type
|
|
|
|
intent.action = forward.action
|
|
|
|
intent.putExtras(forward)
|
|
|
|
}
|
|
|
|
startActivity(intent)
|
|
|
|
finishWithoutSlideOutAnimation()
|
|
|
|
overridePendingTransition(R.anim.explode, R.anim.explode)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun logout() {
|
|
|
|
accountManager.activeAccount?.let { activeAccount ->
|
|
|
|
AlertDialog.Builder(this)
|
2021-06-24 21:23:29 +02:00
|
|
|
.setTitle(R.string.action_logout)
|
|
|
|
.setMessage(getString(R.string.action_logout_confirm, activeAccount.fullName))
|
|
|
|
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
|
2022-06-20 16:45:54 +02:00
|
|
|
binding.appBar.hide()
|
|
|
|
binding.viewPager.hide()
|
|
|
|
binding.progressBar.show()
|
|
|
|
binding.bottomNav.hide()
|
|
|
|
binding.composeButton.hide()
|
|
|
|
|
2021-06-24 21:23:29 +02:00
|
|
|
lifecycleScope.launch {
|
2022-06-20 16:45:54 +02:00
|
|
|
val otherAccountAvailable = logoutUsecase.logout()
|
|
|
|
val intent = if (otherAccountAvailable) {
|
2021-06-24 21:23:29 +02:00
|
|
|
Intent(this@MainActivity, MainActivity::class.java)
|
2022-06-20 16:45:54 +02:00
|
|
|
} else {
|
|
|
|
LoginActivity.getIntent(this@MainActivity, LoginActivity.MODE_DEFAULT)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
startActivity(intent)
|
|
|
|
finishWithoutSlideOutAnimation()
|
|
|
|
}
|
2021-06-24 21:23:29 +02:00
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
|
|
.show()
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
2022-04-14 19:49:49 +02:00
|
|
|
private fun fetchUserInfo() = lifecycleScope.launch {
|
|
|
|
mastodonApi.accountVerifyCredentials().fold(
|
|
|
|
{ userInfo ->
|
|
|
|
onFetchUserInfoSuccess(userInfo)
|
|
|
|
},
|
|
|
|
{ throwable ->
|
|
|
|
Log.e(TAG, "Failed to fetch user info. " + throwable.message)
|
|
|
|
}
|
|
|
|
)
|
2021-06-28 22:04:34 +02:00
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
private fun onFetchUserInfoSuccess(me: Account) {
|
|
|
|
glide.asBitmap()
|
|
|
|
.load(me.header)
|
|
|
|
.into(header.accountHeaderBackground)
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
loadDrawerAvatar(me.avatar, false)
|
2020-09-01 16:49:30 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
accountManager.updateActiveAccount(me)
|
|
|
|
NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this)
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2022-05-17 19:32:09 +02:00
|
|
|
// Setup push notifications
|
2022-06-30 20:49:27 +02:00
|
|
|
showMigrationNoticeIfNecessary(this, binding.mainCoordinatorLayout, binding.composeButton, accountManager)
|
2022-05-17 19:32:09 +02:00
|
|
|
if (NotificationHelper.areNotificationsEnabled(this, accountManager)) {
|
|
|
|
lifecycleScope.launch {
|
|
|
|
enablePushNotificationsWithFallback(this@MainActivity, mastodonApi, accountManager)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
disableAllNotifications(this, accountManager)
|
|
|
|
}
|
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
accountLocked = me.locked
|
2021-04-10 20:30:44 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
updateProfiles()
|
|
|
|
updateShortcut(this, accountManager.activeAccount!!)
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
private fun loadDrawerAvatar(avatarUrl: String, showPlaceholder: Boolean) {
|
2021-06-24 21:23:29 +02:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
2021-12-05 19:12:52 +01:00
|
|
|
val animateAvatars = preferences.getBoolean("animateGifAvatars", false)
|
2020-11-25 19:41:57 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
if (hideTopToolbar) {
|
|
|
|
val navOnBottom = preferences.getString("mainNavPosition", "top") == "bottom"
|
|
|
|
|
|
|
|
val avatarView = if (navOnBottom) {
|
|
|
|
binding.bottomNavAvatar.show()
|
|
|
|
binding.bottomNavAvatar
|
|
|
|
} else {
|
|
|
|
binding.topNavAvatar.show()
|
|
|
|
binding.topNavAvatar
|
|
|
|
}
|
2020-11-25 19:41:57 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
if (animateAvatars) {
|
|
|
|
Glide.with(this)
|
|
|
|
.load(avatarUrl)
|
|
|
|
.placeholder(R.drawable.avatar_default)
|
|
|
|
.into(avatarView)
|
|
|
|
} else {
|
|
|
|
Glide.with(this)
|
|
|
|
.asBitmap()
|
|
|
|
.load(avatarUrl)
|
|
|
|
.placeholder(R.drawable.avatar_default)
|
|
|
|
.into(avatarView)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
binding.bottomNavAvatar.hide()
|
|
|
|
binding.topNavAvatar.hide()
|
|
|
|
|
|
|
|
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size)
|
|
|
|
|
|
|
|
if (animateAvatars) {
|
|
|
|
glide.asDrawable()
|
|
|
|
.load(avatarUrl)
|
|
|
|
.transform(
|
|
|
|
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp))
|
|
|
|
)
|
|
|
|
.apply {
|
|
|
|
if (showPlaceholder) {
|
|
|
|
placeholder(R.drawable.avatar_default)
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
|
|
|
}
|
2022-12-03 12:16:54 +01:00
|
|
|
.into(object : CustomTarget<Drawable>(navIconSize, navIconSize) {
|
2021-12-05 19:12:52 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
override fun onLoadStarted(placeholder: Drawable?) {
|
|
|
|
if (placeholder != null) {
|
|
|
|
binding.mainToolbar.navigationIcon =
|
|
|
|
FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
|
|
|
}
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
2021-03-07 19:29:45 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
override fun onResourceReady(
|
|
|
|
resource: Drawable,
|
|
|
|
transition: Transition<in Drawable>?
|
|
|
|
) {
|
|
|
|
if (resource is Animatable) {
|
|
|
|
resource.start()
|
|
|
|
}
|
|
|
|
binding.mainToolbar.navigationIcon =
|
|
|
|
FixedSizeDrawable(resource, navIconSize, navIconSize)
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
override fun onLoadCleared(placeholder: Drawable?) {
|
|
|
|
if (placeholder != null) {
|
|
|
|
binding.mainToolbar.navigationIcon =
|
|
|
|
FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
glide.asBitmap()
|
|
|
|
.load(avatarUrl)
|
|
|
|
.transform(
|
|
|
|
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp))
|
|
|
|
)
|
|
|
|
.apply {
|
|
|
|
if (showPlaceholder) {
|
|
|
|
placeholder(R.drawable.avatar_default)
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
|
|
|
}
|
2022-12-03 12:16:54 +01:00
|
|
|
.into(object : CustomTarget<Bitmap>(navIconSize, navIconSize) {
|
2021-12-05 19:12:52 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
override fun onLoadStarted(placeholder: Drawable?) {
|
|
|
|
if (placeholder != null) {
|
|
|
|
binding.mainToolbar.navigationIcon =
|
|
|
|
FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
|
|
|
}
|
|
|
|
}
|
2021-12-05 19:12:52 +01:00
|
|
|
|
2022-12-03 12:16:54 +01:00
|
|
|
override fun onResourceReady(
|
|
|
|
resource: Bitmap,
|
|
|
|
transition: Transition<in Bitmap>?
|
|
|
|
) {
|
|
|
|
binding.mainToolbar.navigationIcon = FixedSizeDrawable(
|
|
|
|
BitmapDrawable(resources, resource),
|
|
|
|
navIconSize,
|
|
|
|
navIconSize
|
|
|
|
)
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
2022-12-03 12:16:54 +01:00
|
|
|
|
|
|
|
override fun onLoadCleared(placeholder: Drawable?) {
|
|
|
|
if (placeholder != null) {
|
|
|
|
binding.mainToolbar.navigationIcon =
|
|
|
|
FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2021-12-05 19:12:52 +01:00
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
}
|
2020-11-25 19:41:57 +01:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
private fun fetchAnnouncements() {
|
2022-04-21 18:46:21 +02:00
|
|
|
lifecycleScope.launch {
|
|
|
|
mastodonApi.listAnnouncements(false)
|
|
|
|
.fold(
|
|
|
|
{ announcements ->
|
|
|
|
unreadAnnouncementsCount = announcements.count { !it.read }
|
|
|
|
updateAnnouncementsBadge()
|
|
|
|
},
|
|
|
|
{ throwable ->
|
|
|
|
Log.w(TAG, "Failed to fetch announcements.", throwable)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
}
|
2020-11-18 21:12:27 +01:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
private fun updateAnnouncementsBadge() {
|
|
|
|
binding.mainDrawer.updateBadge(DRAWER_ITEM_ANNOUNCEMENTS, StringHolder(if (unreadAnnouncementsCount <= 0) null else unreadAnnouncementsCount.toString()))
|
|
|
|
}
|
2020-11-18 21:12:27 +01:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
private fun updateProfiles() {
|
|
|
|
val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
|
|
|
|
val profiles: MutableList<IProfile> = accountManager.getAllAccountsOrderedByActive().map { acc ->
|
|
|
|
ProfileDrawerItem().apply {
|
|
|
|
isSelected = acc.isActive
|
2022-04-28 18:55:10 +02:00
|
|
|
nameText = acc.displayName.emojify(acc.emojis, header, animateEmojis)
|
2021-06-28 22:04:34 +02:00
|
|
|
iconUrl = acc.profilePictureUrl
|
|
|
|
isNameShown = true
|
|
|
|
identifier = acc.id
|
|
|
|
descriptionText = acc.fullName
|
|
|
|
}
|
|
|
|
}.toMutableList()
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
// reuse the already existing "add account" item
|
|
|
|
for (profile in header.profiles.orEmpty()) {
|
|
|
|
if (profile.identifier == DRAWER_ITEM_ADD_ACCOUNT) {
|
|
|
|
profiles.add(profile)
|
|
|
|
break
|
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
2021-06-28 22:04:34 +02:00
|
|
|
header.clear()
|
|
|
|
header.profiles = profiles
|
|
|
|
header.setActiveProfile(accountManager.activeAccount!!.id)
|
2022-10-18 19:38:17 +02:00
|
|
|
binding.mainToolbar.subtitle = if (accountManager.shouldDisplaySelfUsername(this)) {
|
2022-09-17 19:05:56 +02:00
|
|
|
accountManager.activeAccount!!.fullName
|
|
|
|
} else null
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
override fun getActionButton() = binding.composeButton
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
override fun androidInjector() = androidInjector
|
2020-04-15 18:57:53 +02:00
|
|
|
|
2021-06-28 22:04:34 +02:00
|
|
|
companion object {
|
|
|
|
private const val TAG = "MainActivity" // logging tag
|
|
|
|
private const val DRAWER_ITEM_ADD_ACCOUNT: Long = -13
|
|
|
|
private const val DRAWER_ITEM_ANNOUNCEMENTS: Long = 14
|
2022-02-25 18:55:58 +01:00
|
|
|
const val REDIRECT_URL = "redirectUrl"
|
2022-08-16 20:08:03 +02:00
|
|
|
const val OPEN_DRAFTS = "draft"
|
2021-06-28 22:04:34 +02:00
|
|
|
}
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private inline fun primaryDrawerItem(block: PrimaryDrawerItem.() -> Unit): PrimaryDrawerItem {
|
|
|
|
return PrimaryDrawerItem()
|
2021-06-24 21:23:29 +02:00
|
|
|
.apply {
|
|
|
|
isSelectable = false
|
|
|
|
isIconTinted = true
|
|
|
|
}
|
|
|
|
.apply(block)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private inline fun secondaryDrawerItem(block: SecondaryDrawerItem.() -> Unit): SecondaryDrawerItem {
|
|
|
|
return SecondaryDrawerItem()
|
2021-06-24 21:23:29 +02:00
|
|
|
.apply {
|
|
|
|
isSelectable = false
|
|
|
|
isIconTinted = true
|
|
|
|
}
|
|
|
|
.apply(block)
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private var AbstractDrawerItem<*, *>.onClick: () -> Unit
|
|
|
|
get() = throw UnsupportedOperationException()
|
|
|
|
set(value) {
|
|
|
|
onDrawerItemClickListener = { _, _, _ ->
|
|
|
|
value()
|
2020-04-28 21:56:02 +02:00
|
|
|
false
|
2020-04-15 18:57:53 +02:00
|
|
|
}
|
2020-11-18 21:12:27 +01:00
|
|
|
}
|