migrating to ViewBinding part 2: Activities (#2093)
This commit is contained in:
parent
5167b8578e
commit
ff69a2ad0d
37 changed files with 741 additions and 729 deletions
|
@ -9,19 +9,20 @@ import android.text.method.LinkMovementMethod
|
|||
import android.text.style.URLSpan
|
||||
import android.text.util.Linkify
|
||||
import android.widget.TextView
|
||||
import com.keylesspalace.tusky.databinding.ActivityAboutBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.util.CustomURLSpan
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import kotlinx.android.synthetic.main.activity_about.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
|
||||
class AboutActivity : BottomSheetActivity(), Injectable {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_about)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
val binding = ActivityAboutBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
|
@ -29,26 +30,24 @@ class AboutActivity : BottomSheetActivity(), Injectable {
|
|||
|
||||
setTitle(R.string.about_title_activity)
|
||||
|
||||
versionTextView.text = getString(R.string.about_app_version, getString(R.string.app_name), BuildConfig.VERSION_NAME)
|
||||
binding.versionTextView.text = getString(R.string.about_app_version, getString(R.string.app_name), BuildConfig.VERSION_NAME)
|
||||
|
||||
if(BuildConfig.CUSTOM_INSTANCE.isBlank()) {
|
||||
aboutPoweredByTusky.hide()
|
||||
binding.aboutPoweredByTusky.hide()
|
||||
}
|
||||
|
||||
aboutLicenseInfoTextView.setClickableTextWithoutUnderlines(R.string.about_tusky_license)
|
||||
aboutWebsiteInfoTextView.setClickableTextWithoutUnderlines(R.string.about_project_site)
|
||||
aboutBugsFeaturesInfoTextView.setClickableTextWithoutUnderlines(R.string.about_bug_feature_request_site)
|
||||
binding.aboutLicenseInfoTextView.setClickableTextWithoutUnderlines(R.string.about_tusky_license)
|
||||
binding.aboutWebsiteInfoTextView.setClickableTextWithoutUnderlines(R.string.about_project_site)
|
||||
binding.aboutBugsFeaturesInfoTextView.setClickableTextWithoutUnderlines(R.string.about_bug_feature_request_site)
|
||||
|
||||
tuskyProfileButton.setOnClickListener {
|
||||
binding.tuskyProfileButton.setOnClickListener {
|
||||
viewUrl(BuildConfig.SUPPORT_ACCOUNT_URL)
|
||||
}
|
||||
|
||||
aboutLicensesButton.setOnClickListener {
|
||||
binding.aboutLicensesButton.setOnClickListener {
|
||||
startActivityWithSlideInAnimation(Intent(this, LicenseActivity::class.java))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun TextView.setClickableTextWithoutUnderlines(@StringRes textId: Int) {
|
||||
|
@ -73,5 +72,4 @@ private fun TextView.setClickableTextWithoutUnderlines(@StringRes textId: Int) {
|
|||
setText(builder)
|
||||
linksClickable = true
|
||||
movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||
import com.keylesspalace.tusky.adapter.AccountFieldAdapter
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||
import com.keylesspalace.tusky.components.report.ReportActivity
|
||||
import com.keylesspalace.tusky.databinding.ActivityAccountBinding
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.entity.Relationship
|
||||
|
@ -63,8 +64,6 @@ import com.keylesspalace.tusky.view.showMuteAccountDialog
|
|||
import com.keylesspalace.tusky.viewmodel.AccountViewModel
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.activity_account.*
|
||||
import kotlinx.android.synthetic.main.view_account_moved.*
|
||||
import java.text.NumberFormat
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
@ -78,6 +77,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
private val viewModel: AccountViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding: ActivityAccountBinding by viewBinding(ActivityAccountBinding::inflate)
|
||||
|
||||
private lateinit var accountFieldAdapter : AccountFieldAdapter
|
||||
|
||||
private var followState: FollowState = FollowState.NOT_FOLLOWING
|
||||
|
@ -118,7 +119,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
super.onCreate(savedInstanceState)
|
||||
loadResources()
|
||||
makeNotificationBarTransparent()
|
||||
setContentView(R.layout.activity_account)
|
||||
setContentView(binding.root)
|
||||
|
||||
// Obtain information to fill out the profile.
|
||||
viewModel.setAccountInfo(intent.getStringExtra(KEY_ACCOUNT_ID)!!)
|
||||
|
@ -136,9 +137,9 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
if (viewModel.isSelf) {
|
||||
updateButtons()
|
||||
saveNoteInfo.hide()
|
||||
binding.saveNoteInfo.hide()
|
||||
} else {
|
||||
saveNoteInfo.visibility = View.INVISIBLE
|
||||
binding.saveNoteInfo.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,16 +159,16 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
*/
|
||||
private fun setupAccountViews() {
|
||||
// Initialise the default UI states.
|
||||
accountFloatingActionButton.hide()
|
||||
accountFollowButton.hide()
|
||||
accountMuteButton.hide()
|
||||
accountFollowsYouTextView.hide()
|
||||
binding.accountFloatingActionButton.hide()
|
||||
binding.accountFollowButton.hide()
|
||||
binding.accountMuteButton.hide()
|
||||
binding.accountFollowsYouTextView.hide()
|
||||
|
||||
// setup the RecyclerView for the account fields
|
||||
accountFieldAdapter = AccountFieldAdapter(this, animateEmojis)
|
||||
accountFieldList.isNestedScrollingEnabled = false
|
||||
accountFieldList.layoutManager = LinearLayoutManager(this)
|
||||
accountFieldList.adapter = accountFieldAdapter
|
||||
binding.accountFieldList.isNestedScrollingEnabled = false
|
||||
binding.accountFieldList.layoutManager = LinearLayoutManager(this)
|
||||
binding.accountFieldList.adapter = accountFieldAdapter
|
||||
|
||||
|
||||
val accountListClickListener = { v: View ->
|
||||
|
@ -179,15 +180,15 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
val accountListIntent = AccountListActivity.newIntent(this, type, viewModel.accountId)
|
||||
startActivityWithSlideInAnimation(accountListIntent)
|
||||
}
|
||||
accountFollowers.setOnClickListener(accountListClickListener)
|
||||
accountFollowing.setOnClickListener(accountListClickListener)
|
||||
binding.accountFollowers.setOnClickListener(accountListClickListener)
|
||||
binding.accountFollowing.setOnClickListener(accountListClickListener)
|
||||
|
||||
accountStatuses.setOnClickListener {
|
||||
binding.accountStatuses.setOnClickListener {
|
||||
// Make nice ripple effect on tab
|
||||
accountTabLayout.getTabAt(0)!!.select()
|
||||
val poorTabView = (accountTabLayout.getChildAt(0) as ViewGroup).getChildAt(0)
|
||||
binding.accountTabLayout.getTabAt(0)!!.select()
|
||||
val poorTabView = (binding.accountTabLayout.getChildAt(0) as ViewGroup).getChildAt(0)
|
||||
poorTabView.isPressed = true
|
||||
accountTabLayout.postDelayed({ poorTabView.isPressed = false }, 300)
|
||||
binding.accountTabLayout.postDelayed({ poorTabView.isPressed = false }, 300)
|
||||
}
|
||||
|
||||
// If wellbeing mode is enabled, follow stats and posts count should be hidden
|
||||
|
@ -195,11 +196,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
val wellbeingEnabled = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_PROFILE, false)
|
||||
|
||||
if (wellbeingEnabled) {
|
||||
accountStatuses.hide()
|
||||
accountFollowers.hide()
|
||||
accountFollowing.hide()
|
||||
binding.accountStatuses.hide()
|
||||
binding.accountFollowers.hide()
|
||||
binding.accountFollowing.hide()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,19 +209,19 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
// Setup the tabs and timeline pager.
|
||||
adapter = AccountPagerAdapter(this, viewModel.accountId)
|
||||
|
||||
accountFragmentViewPager.adapter = adapter
|
||||
accountFragmentViewPager.offscreenPageLimit = 2
|
||||
binding.accountFragmentViewPager.adapter = adapter
|
||||
binding.accountFragmentViewPager.offscreenPageLimit = 2
|
||||
|
||||
val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_statuses_pinned), getString(R.string.title_media))
|
||||
|
||||
TabLayoutMediator(accountTabLayout, accountFragmentViewPager) { tab, position ->
|
||||
TabLayoutMediator(binding.accountTabLayout, binding.accountFragmentViewPager) { tab, position ->
|
||||
tab.text = pageTitles[position]
|
||||
}.attach()
|
||||
|
||||
val pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
|
||||
accountFragmentViewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
||||
binding.accountFragmentViewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
||||
|
||||
accountTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
binding.accountTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||
tab?.position?.let { position ->
|
||||
(adapter.getFragment(position) as? ReselectableFragment)?.onReselect()
|
||||
|
@ -237,17 +237,17 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
private fun setupToolbar() {
|
||||
// set toolbar top margin according to system window insets
|
||||
accountCoordinatorLayout.setOnApplyWindowInsetsListener { _, insets ->
|
||||
binding.accountCoordinatorLayout.setOnApplyWindowInsetsListener { _, insets ->
|
||||
val top = insets.systemWindowInsetTop
|
||||
|
||||
val toolbarParams = accountToolbar.layoutParams as CollapsingToolbarLayout.LayoutParams
|
||||
val toolbarParams = binding.accountToolbar.layoutParams as CollapsingToolbarLayout.LayoutParams
|
||||
toolbarParams.topMargin = top
|
||||
|
||||
insets.consumeSystemWindowInsets()
|
||||
}
|
||||
|
||||
// Setup the toolbar.
|
||||
setSupportActionBar(accountToolbar)
|
||||
setSupportActionBar(binding.accountToolbar)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
|
@ -258,9 +258,9 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
val toolbarBackground = MaterialShapeDrawable.createWithElevationOverlay(this, appBarElevation)
|
||||
toolbarBackground.fillColor = ColorStateList.valueOf(Color.TRANSPARENT)
|
||||
accountToolbar.background = toolbarBackground
|
||||
binding.accountToolbar.background = toolbarBackground
|
||||
|
||||
accountHeaderInfoContainer.background = MaterialShapeDrawable.createWithElevationOverlay(this, appBarElevation)
|
||||
binding.accountHeaderInfoContainer.background = MaterialShapeDrawable.createWithElevationOverlay(this, appBarElevation)
|
||||
|
||||
val avatarBackground = MaterialShapeDrawable.createWithElevationOverlay(this, appBarElevation).apply {
|
||||
fillColor = ColorStateList.valueOf(toolbarColor)
|
||||
|
@ -269,10 +269,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
.setAllCornerSizes(resources.getDimension(R.dimen.account_avatar_background_radius))
|
||||
.build()
|
||||
}
|
||||
accountAvatarImageView.background = avatarBackground
|
||||
binding.accountAvatarImageView.background = avatarBackground
|
||||
|
||||
// Add a listener to change the toolbar icon color when it enters/exits its collapsed state.
|
||||
accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
|
||||
binding.accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
|
||||
|
||||
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
|
||||
|
||||
|
@ -289,19 +289,19 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
if (hideFab && !viewModel.isSelf && !blocking) {
|
||||
if (verticalOffset > oldOffset) {
|
||||
accountFloatingActionButton.show()
|
||||
binding.accountFloatingActionButton.show()
|
||||
}
|
||||
if (verticalOffset < oldOffset) {
|
||||
accountFloatingActionButton.hide()
|
||||
binding.accountFloatingActionButton.hide()
|
||||
}
|
||||
}
|
||||
|
||||
val scaledAvatarSize = (avatarSize + verticalOffset) / avatarSize
|
||||
|
||||
accountAvatarImageView.scaleX = scaledAvatarSize
|
||||
accountAvatarImageView.scaleY = scaledAvatarSize
|
||||
binding.accountAvatarImageView.scaleX = scaledAvatarSize
|
||||
binding.accountAvatarImageView.scaleY = scaledAvatarSize
|
||||
|
||||
accountAvatarImageView.visible(scaledAvatarSize > 0)
|
||||
binding.accountAvatarImageView.visible(scaledAvatarSize > 0)
|
||||
|
||||
val transparencyPercent = (abs(verticalOffset) / titleVisibleHeight.toFloat()).coerceAtMost(1f)
|
||||
|
||||
|
@ -311,7 +311,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
toolbarBackground.fillColor = ColorStateList.valueOf(evaluatedToolbarColor)
|
||||
|
||||
swipeToRefreshLayout.isEnabled = verticalOffset == 0
|
||||
binding.swipeToRefreshLayout.isEnabled = verticalOffset == 0
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -331,7 +331,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
when (it) {
|
||||
is Success -> onAccountChanged(it.data)
|
||||
is Error -> {
|
||||
Snackbar.make(accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
Snackbar.make(binding.accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.action_retry) { viewModel.refresh() }
|
||||
.show()
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
}
|
||||
|
||||
if (it is Error) {
|
||||
Snackbar.make(accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
Snackbar.make(binding.accountCoordinatorLayout, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.action_retry) { viewModel.refresh() }
|
||||
.show()
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
accountFieldAdapter.notifyDataSetChanged()
|
||||
})
|
||||
viewModel.noteSaved.observe(this) {
|
||||
saveNoteInfo.visible(it, View.INVISIBLE)
|
||||
binding.saveNoteInfo.visible(it, View.INVISIBLE)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,32 +363,32 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
* Setup swipe to refresh layout
|
||||
*/
|
||||
private fun setupRefreshLayout() {
|
||||
swipeToRefreshLayout.setOnRefreshListener {
|
||||
binding.swipeToRefreshLayout.setOnRefreshListener {
|
||||
viewModel.refresh()
|
||||
adapter.refreshContent()
|
||||
}
|
||||
viewModel.isRefreshing.observe(this, { isRefreshing ->
|
||||
swipeToRefreshLayout.isRefreshing = isRefreshing == true
|
||||
binding.swipeToRefreshLayout.isRefreshing = isRefreshing == true
|
||||
})
|
||||
swipeToRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
binding.swipeToRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
}
|
||||
|
||||
private fun onAccountChanged(account: Account?) {
|
||||
loadedAccount = account ?: return
|
||||
|
||||
val usernameFormatted = getString(R.string.status_username_format, account.username)
|
||||
accountUsernameTextView.text = usernameFormatted
|
||||
accountDisplayNameTextView.text = account.name.emojify(account.emojis, accountDisplayNameTextView, animateEmojis)
|
||||
binding.accountUsernameTextView.text = usernameFormatted
|
||||
binding.accountDisplayNameTextView.text = account.name.emojify(account.emojis, binding.accountDisplayNameTextView, animateEmojis)
|
||||
|
||||
val emojifiedNote = account.note.emojify(account.emojis, accountNoteTextView, animateEmojis)
|
||||
LinkHelper.setClickableText(accountNoteTextView, emojifiedNote, null, this)
|
||||
val emojifiedNote = account.note.emojify(account.emojis, binding.accountNoteTextView, animateEmojis)
|
||||
LinkHelper.setClickableText(binding.accountNoteTextView, emojifiedNote, null, this)
|
||||
|
||||
// accountFieldAdapter.fields = account.fields ?: emptyList()
|
||||
accountFieldAdapter.emojis = account.emojis ?: emptyList()
|
||||
accountFieldAdapter.notifyDataSetChanged()
|
||||
|
||||
accountLockedImageView.visible(account.locked)
|
||||
accountBadgeTextView.visible(account.bot)
|
||||
binding.accountLockedImageView.visible(account.locked)
|
||||
binding.accountBadgeTextView.visible(account.bot)
|
||||
|
||||
updateAccountAvatar()
|
||||
updateToolbar()
|
||||
|
@ -397,7 +397,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
updateAccountStats()
|
||||
invalidateOptionsMenu()
|
||||
|
||||
accountMuteButton.setOnClickListener {
|
||||
binding.accountMuteButton.setOnClickListener {
|
||||
viewModel.unmuteAccount()
|
||||
updateMuteButton()
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
loadAvatar(
|
||||
account.avatar,
|
||||
accountAvatarImageView,
|
||||
binding.accountAvatarImageView,
|
||||
resources.getDimensionPixelSize(R.dimen.avatar_radius_94dp),
|
||||
animateAvatar
|
||||
)
|
||||
|
@ -420,10 +420,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
.asBitmap()
|
||||
.load(account.header)
|
||||
.centerCrop()
|
||||
.into(accountHeaderImageView)
|
||||
.into(binding.accountHeaderImageView)
|
||||
|
||||
|
||||
accountAvatarImageView.setOnClickListener { avatarView ->
|
||||
binding.accountAvatarImageView.setOnClickListener { avatarView ->
|
||||
val intent = ViewMediaActivity.newSingleImageIntent(avatarView.context, account.avatar)
|
||||
|
||||
avatarView.transitionName = account.avatar
|
||||
|
@ -440,7 +440,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
private fun updateToolbar() {
|
||||
loadedAccount?.let { account ->
|
||||
|
||||
val emojifiedName = account.name.emojify(account.emojis, accountToolbar, animateEmojis)
|
||||
val emojifiedName = account.name.emojify(account.emojis, binding.accountToolbar, animateEmojis)
|
||||
|
||||
try {
|
||||
supportActionBar?.title = EmojiCompat.get().process(emojifiedName)
|
||||
|
@ -457,28 +457,27 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
private fun updateMovedAccount() {
|
||||
loadedAccount?.moved?.let { movedAccount ->
|
||||
|
||||
accountMovedView?.show()
|
||||
binding.accountMovedView.show()
|
||||
|
||||
// necessary because accountMovedView is now replaced in layout hierachy
|
||||
findViewById<View>(R.id.accountMovedViewLayout).setOnClickListener {
|
||||
binding.accountMovedView.setOnClickListener {
|
||||
onViewAccount(movedAccount.id)
|
||||
}
|
||||
|
||||
accountMovedDisplayName.text = movedAccount.name
|
||||
accountMovedUsername.text = getString(R.string.status_username_format, movedAccount.username)
|
||||
binding.accountMovedDisplayName.text = movedAccount.name
|
||||
binding.accountMovedUsername.text = getString(R.string.status_username_format, movedAccount.username)
|
||||
|
||||
val avatarRadius = resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp)
|
||||
|
||||
loadAvatar(movedAccount.avatar, accountMovedAvatar, avatarRadius, animateAvatar)
|
||||
loadAvatar(movedAccount.avatar, binding.accountMovedAvatar, avatarRadius, animateAvatar)
|
||||
|
||||
accountMovedText.text = getString(R.string.account_moved_description, movedAccount.name)
|
||||
binding.accountMovedText.text = getString(R.string.account_moved_description, movedAccount.name)
|
||||
|
||||
// this is necessary because API 19 can't handle vector compound drawables
|
||||
val movedIcon = ContextCompat.getDrawable(this, R.drawable.ic_briefcase)?.mutate()
|
||||
val textColor = ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
movedIcon?.colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
accountMovedText.setCompoundDrawablesRelativeWithIntrinsicBounds(movedIcon, null, null, null)
|
||||
binding.accountMovedText.setCompoundDrawablesRelativeWithIntrinsicBounds(movedIcon, null, null, null)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -489,8 +488,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
private fun updateRemoteAccount() {
|
||||
loadedAccount?.let { account ->
|
||||
if (account.isRemote()) {
|
||||
accountRemoveView.show()
|
||||
accountRemoveView.setOnClickListener {
|
||||
binding.accountRemoveView.show()
|
||||
binding.accountRemoveView.setOnClickListener {
|
||||
LinkHelper.openLink(account.url, this)
|
||||
}
|
||||
}
|
||||
|
@ -503,13 +502,13 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
private fun updateAccountStats() {
|
||||
loadedAccount?.let { account ->
|
||||
val numberFormat = NumberFormat.getNumberInstance()
|
||||
accountFollowersTextView.text = numberFormat.format(account.followersCount)
|
||||
accountFollowingTextView.text = numberFormat.format(account.followingCount)
|
||||
accountStatusesTextView.text = numberFormat.format(account.statusesCount)
|
||||
binding.accountFollowersTextView.text = numberFormat.format(account.followersCount)
|
||||
binding.accountFollowingTextView.text = numberFormat.format(account.followingCount)
|
||||
binding.accountStatusesTextView.text = numberFormat.format(account.statusesCount)
|
||||
|
||||
accountFloatingActionButton.setOnClickListener { mention() }
|
||||
binding.accountFloatingActionButton.setOnClickListener { mention() }
|
||||
|
||||
accountFollowButton.setOnClickListener {
|
||||
binding.accountFollowButton.setOnClickListener {
|
||||
if (viewModel.isSelf) {
|
||||
val intent = Intent(this@AccountActivity, EditProfileActivity::class.java)
|
||||
startActivity(intent)
|
||||
|
@ -552,14 +551,14 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val wellbeingEnabled = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_PROFILE, false)
|
||||
|
||||
accountFollowsYouTextView.visible(relation.followedBy && !wellbeingEnabled)
|
||||
binding.accountFollowsYouTextView.visible(relation.followedBy && !wellbeingEnabled)
|
||||
|
||||
// because subscribing is Pleroma extension, enable it __only__ when we have non-null subscribing field
|
||||
// it's also now supported in Mastodon 3.3.0rc but called notifying and use different API call
|
||||
if(!viewModel.isSelf && followState == FollowState.FOLLOWING
|
||||
&& (relation.subscribing != null || relation.notifying != null)) {
|
||||
accountSubscribeButton.show()
|
||||
accountSubscribeButton.setOnClickListener {
|
||||
binding.accountSubscribeButton.show()
|
||||
binding.accountSubscribeButton.setOnClickListener {
|
||||
viewModel.changeSubscribingState()
|
||||
}
|
||||
if(relation.notifying != null)
|
||||
|
@ -569,12 +568,12 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
}
|
||||
|
||||
// remove the listener so it doesn't fire on non-user changes
|
||||
accountNoteTextInputLayout.editText?.removeTextChangedListener(noteWatcher)
|
||||
binding.accountNoteTextInputLayout.editText?.removeTextChangedListener(noteWatcher)
|
||||
|
||||
accountNoteTextInputLayout.visible(relation.note != null)
|
||||
accountNoteTextInputLayout.editText?.setText(relation.note)
|
||||
binding.accountNoteTextInputLayout.visible(relation.note != null)
|
||||
binding.accountNoteTextInputLayout.editText?.setText(relation.note)
|
||||
|
||||
accountNoteTextInputLayout.editText?.addTextChangedListener(noteWatcher)
|
||||
binding.accountNoteTextInputLayout.editText?.addTextChangedListener(noteWatcher)
|
||||
|
||||
updateButtons()
|
||||
}
|
||||
|
@ -587,22 +586,22 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
private fun updateFollowButton() {
|
||||
if (viewModel.isSelf) {
|
||||
accountFollowButton.setText(R.string.action_edit_own_profile)
|
||||
binding.accountFollowButton.setText(R.string.action_edit_own_profile)
|
||||
return
|
||||
}
|
||||
if (blocking) {
|
||||
accountFollowButton.setText(R.string.action_unblock)
|
||||
binding.accountFollowButton.setText(R.string.action_unblock)
|
||||
return
|
||||
}
|
||||
when (followState) {
|
||||
FollowState.NOT_FOLLOWING -> {
|
||||
accountFollowButton.setText(R.string.action_follow)
|
||||
binding.accountFollowButton.setText(R.string.action_follow)
|
||||
}
|
||||
FollowState.REQUESTED -> {
|
||||
accountFollowButton.setText(R.string.state_follow_requested)
|
||||
binding.accountFollowButton.setText(R.string.state_follow_requested)
|
||||
}
|
||||
FollowState.FOLLOWING -> {
|
||||
accountFollowButton.setText(R.string.action_unfollow)
|
||||
binding.accountFollowButton.setText(R.string.action_unfollow)
|
||||
}
|
||||
}
|
||||
updateSubscribeButton()
|
||||
|
@ -610,23 +609,23 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
private fun updateMuteButton() {
|
||||
if (muting) {
|
||||
accountMuteButton.setIconResource(R.drawable.ic_unmute_24dp)
|
||||
binding.accountMuteButton.setIconResource(R.drawable.ic_unmute_24dp)
|
||||
} else {
|
||||
accountMuteButton.hide()
|
||||
binding.accountMuteButton.hide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSubscribeButton() {
|
||||
if(followState != FollowState.FOLLOWING) {
|
||||
accountSubscribeButton.hide()
|
||||
binding.accountSubscribeButton.hide()
|
||||
}
|
||||
|
||||
if(subscribing) {
|
||||
accountSubscribeButton.setIconResource(R.drawable.ic_notifications_active_24dp)
|
||||
accountSubscribeButton.contentDescription = getString(R.string.action_unsubscribe_account)
|
||||
binding.accountSubscribeButton.setIconResource(R.drawable.ic_notifications_active_24dp)
|
||||
binding.accountSubscribeButton.contentDescription = getString(R.string.action_unsubscribe_account)
|
||||
} else {
|
||||
accountSubscribeButton.setIconResource(R.drawable.ic_notifications_24dp)
|
||||
accountSubscribeButton.contentDescription = getString(R.string.action_subscribe_account)
|
||||
binding.accountSubscribeButton.setIconResource(R.drawable.ic_notifications_24dp)
|
||||
binding.accountSubscribeButton.contentDescription = getString(R.string.action_subscribe_account)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,27 +634,27 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
if (loadedAccount?.moved == null) {
|
||||
|
||||
accountFollowButton.show()
|
||||
binding.accountFollowButton.show()
|
||||
updateFollowButton()
|
||||
|
||||
if (blocking || viewModel.isSelf) {
|
||||
accountFloatingActionButton.hide()
|
||||
accountMuteButton.hide()
|
||||
accountSubscribeButton.hide()
|
||||
binding.accountFloatingActionButton.hide()
|
||||
binding.accountMuteButton.hide()
|
||||
binding.accountSubscribeButton.hide()
|
||||
} else {
|
||||
accountFloatingActionButton.show()
|
||||
binding.accountFloatingActionButton.show()
|
||||
if (muting)
|
||||
accountMuteButton.show()
|
||||
binding.accountMuteButton.show()
|
||||
else
|
||||
accountMuteButton.hide()
|
||||
binding.accountMuteButton.hide()
|
||||
updateMuteButton()
|
||||
}
|
||||
|
||||
} else {
|
||||
accountFloatingActionButton.hide()
|
||||
accountFollowButton.hide()
|
||||
accountMuteButton.hide()
|
||||
accountSubscribeButton.hide()
|
||||
binding.accountFloatingActionButton.hide()
|
||||
binding.accountFollowButton.hide()
|
||||
binding.accountMuteButton.hide()
|
||||
binding.accountSubscribeButton.hide()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,7 +832,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
|||
|
||||
override fun getActionButton(): FloatingActionButton? {
|
||||
return if (!viewModel.isSelf && !blocking) {
|
||||
accountFloatingActionButton
|
||||
binding.accountFloatingActionButton
|
||||
} else null
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ package com.keylesspalace.tusky
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
|
||||
import com.keylesspalace.tusky.fragment.AccountListFragment
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class AccountListActivity : BaseActivity(), HasAndroidInjector {
|
||||
|
@ -41,12 +41,13 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_account_list)
|
||||
val binding = ActivityAccountListBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val type = intent.getSerializableExtra(EXTRA_TYPE) as Type
|
||||
val id: String? = intent.getStringExtra(EXTRA_ID)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.apply {
|
||||
when (type) {
|
||||
Type.BLOCKS -> setTitle(R.string.title_blocks)
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.bumptech.glide.load.resource.bitmap.FitCenter
|
|||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.keylesspalace.tusky.adapter.AccountFieldEditAdapter
|
||||
import com.keylesspalace.tusky.databinding.ActivityEditProfileBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.util.*
|
||||
|
@ -47,8 +48,6 @@ import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
|||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import com.theartofdev.edmodo.cropper.CropImage
|
||||
import kotlinx.android.synthetic.main.activity_edit_profile.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class EditProfileActivity : BaseActivity(), Injectable {
|
||||
|
@ -71,6 +70,8 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
|
||||
private val viewModel: EditProfileViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivityEditProfileBinding::inflate)
|
||||
|
||||
private var currentlyPicking: PickType = PickType.NOTHING
|
||||
|
||||
private val accountFieldEditAdapter = AccountFieldEditAdapter()
|
||||
|
@ -88,33 +89,33 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
currentlyPicking = PickType.valueOf(it)
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_edit_profile)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
setTitle(R.string.title_edit_profile)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
avatarButton.setOnClickListener { onMediaPick(PickType.AVATAR) }
|
||||
headerButton.setOnClickListener { onMediaPick(PickType.HEADER) }
|
||||
binding.avatarButton.setOnClickListener { onMediaPick(PickType.AVATAR) }
|
||||
binding.headerButton.setOnClickListener { onMediaPick(PickType.HEADER) }
|
||||
|
||||
fieldList.layoutManager = LinearLayoutManager(this)
|
||||
fieldList.adapter = accountFieldEditAdapter
|
||||
binding.fieldList.layoutManager = LinearLayoutManager(this)
|
||||
binding.fieldList.adapter = accountFieldEditAdapter
|
||||
|
||||
val plusDrawable = IconicsDrawable(this, GoogleMaterial.Icon.gmd_add).apply { sizeDp = 12; colorInt = Color.WHITE }
|
||||
|
||||
addFieldButton.setCompoundDrawablesRelativeWithIntrinsicBounds(plusDrawable, null, null, null)
|
||||
binding.addFieldButton.setCompoundDrawablesRelativeWithIntrinsicBounds(plusDrawable, null, null, null)
|
||||
|
||||
addFieldButton.setOnClickListener {
|
||||
binding.addFieldButton.setOnClickListener {
|
||||
accountFieldEditAdapter.addField()
|
||||
if(accountFieldEditAdapter.itemCount >= MAX_ACCOUNT_FIELDS) {
|
||||
it.isVisible = false
|
||||
}
|
||||
|
||||
scrollView.post{
|
||||
scrollView.smoothScrollTo(0, it.bottom)
|
||||
binding.scrollView.post{
|
||||
binding.scrollView.smoothScrollTo(0, it.bottom)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,12 +127,12 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
val me = profileRes.data
|
||||
if (me != null) {
|
||||
|
||||
displayNameEditText.setText(me.displayName)
|
||||
noteEditText.setText(me.source?.note)
|
||||
lockedCheckBox.isChecked = me.locked
|
||||
binding.displayNameEditText.setText(me.displayName)
|
||||
binding.noteEditText.setText(me.source?.note)
|
||||
binding.lockedCheckBox.isChecked = me.locked
|
||||
|
||||
accountFieldEditAdapter.setFields(me.source?.fields ?: emptyList())
|
||||
addFieldButton.isEnabled = me.source?.fields?.size ?: 0 < MAX_ACCOUNT_FIELDS
|
||||
binding.addFieldButton.isEnabled = me.source?.fields?.size ?: 0 < MAX_ACCOUNT_FIELDS
|
||||
|
||||
if(viewModel.avatarData.value == null) {
|
||||
Glide.with(this)
|
||||
|
@ -141,19 +142,19 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
FitCenter(),
|
||||
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp))
|
||||
)
|
||||
.into(avatarPreview)
|
||||
.into(binding.avatarPreview)
|
||||
}
|
||||
|
||||
if(viewModel.headerData.value == null) {
|
||||
Glide.with(this)
|
||||
.load(me.header)
|
||||
.into(headerPreview)
|
||||
.into(binding.headerPreview)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
is Error -> {
|
||||
val snackbar = Snackbar.make(avatarButton, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
val snackbar = Snackbar.make(binding.avatarButton, R.string.error_generic, Snackbar.LENGTH_LONG)
|
||||
snackbar.setAction(R.string.action_retry) {
|
||||
viewModel.obtainProfile()
|
||||
}
|
||||
|
@ -169,14 +170,14 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
is Success -> {
|
||||
val instance = result.data
|
||||
if (instance?.maxBioChars != null && instance.maxBioChars > 0) {
|
||||
noteEditTextLayout.counterMaxLength = instance.maxBioChars
|
||||
binding.noteEditTextLayout.counterMaxLength = instance.maxBioChars
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
observeImage(viewModel.avatarData, avatarPreview, avatarProgressBar, true)
|
||||
observeImage(viewModel.headerData, headerPreview, headerProgressBar, false)
|
||||
observeImage(viewModel.avatarData, binding.avatarPreview, binding.avatarProgressBar, true)
|
||||
observeImage(viewModel.headerData, binding.headerPreview, binding.headerProgressBar, false)
|
||||
|
||||
viewModel.saveData.observe(this, {
|
||||
when(it) {
|
||||
|
@ -184,7 +185,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
finish()
|
||||
}
|
||||
is Loading -> {
|
||||
saveProgressBar.visibility = View.VISIBLE
|
||||
binding.saveProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
is Error -> {
|
||||
onSaveFailure(it.errorMessage)
|
||||
|
@ -202,9 +203,9 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
override fun onStop() {
|
||||
super.onStop()
|
||||
if(!isFinishing) {
|
||||
viewModel.updateProfile(displayNameEditText.text.toString(),
|
||||
noteEditText.text.toString(),
|
||||
lockedCheckBox.isChecked,
|
||||
viewModel.updateProfile(binding.displayNameEditText.text.toString(),
|
||||
binding.noteEditText.text.toString(),
|
||||
binding.lockedCheckBox.isChecked,
|
||||
accountFieldEditAdapter.getFieldData())
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +269,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
initiateMediaPicking()
|
||||
} else {
|
||||
endMediaPicking()
|
||||
Snackbar.make(avatarButton, R.string.error_media_upload_permission, Snackbar.LENGTH_LONG).show()
|
||||
Snackbar.make(binding.avatarButton, R.string.error_media_upload_permission, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,39 +310,38 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
return
|
||||
}
|
||||
|
||||
viewModel.save(displayNameEditText.text.toString(),
|
||||
noteEditText.text.toString(),
|
||||
lockedCheckBox.isChecked,
|
||||
viewModel.save(binding.displayNameEditText.text.toString(),
|
||||
binding.noteEditText.text.toString(),
|
||||
binding.lockedCheckBox.isChecked,
|
||||
accountFieldEditAdapter.getFieldData(),
|
||||
this)
|
||||
}
|
||||
|
||||
private fun onSaveFailure(msg: String?) {
|
||||
val errorMsg = msg ?: getString(R.string.error_media_upload_sending)
|
||||
Snackbar.make(avatarButton, errorMsg, Snackbar.LENGTH_LONG).show()
|
||||
saveProgressBar.visibility = View.GONE
|
||||
Snackbar.make(binding.avatarButton, errorMsg, Snackbar.LENGTH_LONG).show()
|
||||
binding.saveProgressBar.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun beginMediaPicking() {
|
||||
when (currentlyPicking) {
|
||||
PickType.AVATAR -> {
|
||||
avatarProgressBar.visibility = View.VISIBLE
|
||||
avatarPreview.visibility = View.INVISIBLE
|
||||
avatarButton.setImageDrawable(null)
|
||||
|
||||
binding.avatarProgressBar.visibility = View.VISIBLE
|
||||
binding.avatarPreview.visibility = View.INVISIBLE
|
||||
binding.avatarButton.setImageDrawable(null)
|
||||
}
|
||||
PickType.HEADER -> {
|
||||
headerProgressBar.visibility = View.VISIBLE
|
||||
headerPreview.visibility = View.INVISIBLE
|
||||
headerButton.setImageDrawable(null)
|
||||
binding.headerProgressBar.visibility = View.VISIBLE
|
||||
binding.headerPreview.visibility = View.INVISIBLE
|
||||
binding.headerButton.setImageDrawable(null)
|
||||
}
|
||||
PickType.NOTHING -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
|
||||
private fun endMediaPicking() {
|
||||
avatarProgressBar.visibility = View.GONE
|
||||
headerProgressBar.visibility = View.GONE
|
||||
binding.avatarProgressBar.visibility = View.GONE
|
||||
binding.headerProgressBar.visibility = View.GONE
|
||||
|
||||
currentlyPicking = PickType.NOTHING
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
|
|||
}
|
||||
|
||||
private fun onResizeFailure() {
|
||||
Snackbar.make(avatarButton, R.string.error_media_upload_sending, Snackbar.LENGTH_LONG).show()
|
||||
Snackbar.make(binding.avatarButton, R.string.error_media_upload_sending, Snackbar.LENGTH_LONG).show()
|
||||
endMediaPicking()
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ import android.widget.Toast
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
|
||||
import com.keylesspalace.tusky.databinding.ActivityFiltersBinding
|
||||
import com.keylesspalace.tusky.databinding.DialogFilterBinding
|
||||
import com.keylesspalace.tusky.entity.Filter
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.show
|
||||
import kotlinx.android.synthetic.main.activity_filters.*
|
||||
import kotlinx.android.synthetic.main.dialog_filter.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
|
@ -28,13 +28,28 @@ class FiltersActivity: BaseActivity() {
|
|||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
private val binding by viewBinding(ActivityFiltersBinding::inflate)
|
||||
|
||||
private lateinit var context : String
|
||||
private lateinit var filters: MutableList<Filter>
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
companion object {
|
||||
const val FILTERS_CONTEXT = "filters_context"
|
||||
const val FILTERS_TITLE = "filters_title"
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(binding.root)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
// Back button
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
binding.addFilterButton.setOnClickListener {
|
||||
showAddFilterDialog()
|
||||
}
|
||||
|
||||
title = intent?.getStringExtra(FILTERS_TITLE)
|
||||
context = intent?.getStringExtra(FILTERS_CONTEXT)!!
|
||||
loadFilters()
|
||||
}
|
||||
|
||||
private fun updateFilter(filter: Filter, itemIndex: Int) {
|
||||
|
@ -101,52 +116,51 @@ class FiltersActivity: BaseActivity() {
|
|||
}
|
||||
|
||||
private fun showAddFilterDialog() {
|
||||
dialog = AlertDialog.Builder(this@FiltersActivity)
|
||||
val binding = DialogFilterBinding.inflate(layoutInflater)
|
||||
binding.phraseWholeWord.isChecked = true
|
||||
AlertDialog.Builder(this@FiltersActivity)
|
||||
.setTitle(R.string.filter_addition_dialog_title)
|
||||
.setView(R.layout.dialog_filter)
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(android.R.string.ok){ _, _ ->
|
||||
createFilter(dialog.phraseEditText.text.toString(), dialog.phraseWholeWord.isChecked)
|
||||
createFilter(binding.phraseEditText.text.toString(), binding.phraseWholeWord.isChecked)
|
||||
}
|
||||
.setNeutralButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
dialog.show()
|
||||
dialog.phraseWholeWord.isChecked = true
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun setupEditDialogForItem(itemIndex: Int) {
|
||||
dialog = AlertDialog.Builder(this@FiltersActivity)
|
||||
val binding = DialogFilterBinding.inflate(layoutInflater)
|
||||
val filter = filters[itemIndex]
|
||||
binding.phraseEditText.setText(filter.phrase)
|
||||
binding.phraseWholeWord.isChecked = filter.wholeWord
|
||||
|
||||
AlertDialog.Builder(this@FiltersActivity)
|
||||
.setTitle(R.string.filter_edit_dialog_title)
|
||||
.setView(R.layout.dialog_filter)
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(R.string.filter_dialog_update_button) { _, _ ->
|
||||
val oldFilter = filters[itemIndex]
|
||||
val newFilter = Filter(oldFilter.id, dialog.phraseEditText.text.toString(), oldFilter.context,
|
||||
oldFilter.expiresAt, oldFilter.irreversible, dialog.phraseWholeWord.isChecked)
|
||||
val newFilter = Filter(oldFilter.id, binding.phraseEditText.text.toString(), oldFilter.context,
|
||||
oldFilter.expiresAt, oldFilter.irreversible, binding.phraseWholeWord.isChecked)
|
||||
updateFilter(newFilter, itemIndex)
|
||||
}
|
||||
.setNegativeButton(R.string.filter_dialog_remove_button) { _, _ ->
|
||||
deleteFilter(itemIndex)
|
||||
}
|
||||
.setNeutralButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
dialog.show()
|
||||
|
||||
// Need to show the dialog before referencing any elements from its view
|
||||
val filter = filters[itemIndex]
|
||||
dialog.phraseEditText.setText(filter.phrase)
|
||||
dialog.phraseWholeWord.isChecked = filter.wholeWord
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun refreshFilterDisplay() {
|
||||
filtersView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, filters.map { filter -> filter.phrase })
|
||||
filtersView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> setupEditDialogForItem(position) }
|
||||
binding.filtersView.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, filters.map { filter -> filter.phrase })
|
||||
binding.filtersView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> setupEditDialogForItem(position) }
|
||||
}
|
||||
|
||||
private fun loadFilters() {
|
||||
|
||||
filterMessageView.hide()
|
||||
filtersView.hide()
|
||||
addFilterButton.hide()
|
||||
filterProgressBar.show()
|
||||
binding.filterMessageView.hide()
|
||||
binding.filtersView.hide()
|
||||
binding.addFilterButton.hide()
|
||||
binding.filterProgressBar.show()
|
||||
|
||||
api.getFilters().enqueue(object : Callback<List<Filter>> {
|
||||
override fun onResponse(call: Call<List<Filter>>, response: Response<List<Filter>>) {
|
||||
|
@ -156,52 +170,33 @@ class FiltersActivity: BaseActivity() {
|
|||
filters = filterResponse.filter { filter -> filter.context.contains(context) }.toMutableList()
|
||||
refreshFilterDisplay()
|
||||
|
||||
filtersView.show()
|
||||
addFilterButton.show()
|
||||
filterProgressBar.hide()
|
||||
binding.filtersView.show()
|
||||
binding.addFilterButton.show()
|
||||
binding.filterProgressBar.hide()
|
||||
} else {
|
||||
filterProgressBar.hide()
|
||||
filterMessageView.show()
|
||||
filterMessageView.setup(R.drawable.elephant_error,
|
||||
binding.filterProgressBar.hide()
|
||||
binding.filterMessageView.show()
|
||||
binding.filterMessageView.setup(R.drawable.elephant_error,
|
||||
R.string.error_generic) { loadFilters() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<List<Filter>>, t: Throwable) {
|
||||
filterProgressBar.hide()
|
||||
filterMessageView.show()
|
||||
binding.filterProgressBar.hide()
|
||||
binding.filterMessageView.show()
|
||||
if (t is IOException) {
|
||||
filterMessageView.setup(R.drawable.elephant_offline,
|
||||
binding.filterMessageView.setup(R.drawable.elephant_offline,
|
||||
R.string.error_network) { loadFilters() }
|
||||
} else {
|
||||
filterMessageView.setup(R.drawable.elephant_error,
|
||||
binding.filterMessageView.setup(R.drawable.elephant_error,
|
||||
R.string.error_generic) { loadFilters() }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_filters)
|
||||
setupToolbarBackArrow()
|
||||
addFilterButton.setOnClickListener {
|
||||
showAddFilterDialog()
|
||||
}
|
||||
|
||||
title = intent?.getStringExtra(FILTERS_TITLE)
|
||||
context = intent?.getStringExtra(FILTERS_CONTEXT)!!
|
||||
loadFilters()
|
||||
}
|
||||
|
||||
private fun setupToolbarBackArrow() {
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.run {
|
||||
// Back button
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
companion object {
|
||||
const val FILTERS_CONTEXT = "filters_context"
|
||||
const val FILTERS_TITLE = "filters_title"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,23 +19,20 @@ import android.os.Bundle
|
|||
import androidx.annotation.RawRes
|
||||
import android.util.Log
|
||||
import android.widget.TextView
|
||||
import com.keylesspalace.tusky.databinding.ActivityLicenseBinding
|
||||
import com.keylesspalace.tusky.util.IOUtils
|
||||
import kotlinx.android.extensions.CacheImplementation
|
||||
import kotlinx.android.extensions.ContainerOptions
|
||||
import kotlinx.android.synthetic.main.activity_license.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
|
||||
class LicenseActivity : BaseActivity() {
|
||||
|
||||
@ContainerOptions(cache = CacheImplementation.NO_CACHE)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_license)
|
||||
val binding = ActivityLicenseBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
|
@ -43,7 +40,7 @@ class LicenseActivity : BaseActivity() {
|
|||
|
||||
setTitle(R.string.title_licenses)
|
||||
|
||||
loadFileIntoTextView(R.raw.apache, licenseApacheTextView)
|
||||
loadFileIntoTextView(R.raw.apache, binding.licenseApacheTextView)
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,7 +64,5 @@ class LicenseActivity : BaseActivity() {
|
|||
IOUtils.closeQuietly(br)
|
||||
|
||||
textView.text = sb.toString()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,12 +24,14 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import at.connyduck.sparkbutton.helpers.Utils
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.keylesspalace.tusky.databinding.ActivityListsBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.MastoList
|
||||
|
@ -47,8 +49,6 @@ import com.uber.autodispose.autoDispose
|
|||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.android.synthetic.main.activity_lists.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
@ -57,47 +57,42 @@ import javax.inject.Inject
|
|||
|
||||
class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context): Intent {
|
||||
return Intent(context, ListsActivity::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelFactory
|
||||
|
||||
@Inject
|
||||
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
private lateinit var viewModel: ListsViewModel
|
||||
private val viewModel: ListsViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivityListsBinding::inflate)
|
||||
|
||||
private val adapter = ListsAdapter()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_lists)
|
||||
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.apply {
|
||||
title = getString(R.string.title_lists)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
listsRecycler.adapter = adapter
|
||||
listsRecycler.layoutManager = LinearLayoutManager(this)
|
||||
listsRecycler.addItemDecoration(
|
||||
binding.listsRecycler.adapter = adapter
|
||||
binding.listsRecycler.layoutManager = LinearLayoutManager(this)
|
||||
binding.listsRecycler.addItemDecoration(
|
||||
DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
|
||||
|
||||
viewModel = viewModelFactory.create(ListsViewModel::class.java)
|
||||
viewModel.state
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(from(this))
|
||||
.subscribe(this::update)
|
||||
viewModel.retryLoading()
|
||||
|
||||
addListButton.setOnClickListener {
|
||||
binding.addListButton.setOnClickListener {
|
||||
showlistNameDialog(null)
|
||||
}
|
||||
|
||||
|
@ -153,37 +148,36 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
|||
|
||||
private fun update(state: ListsViewModel.State) {
|
||||
adapter.submitList(state.lists)
|
||||
progressBar.visible(state.loadingState == LOADING)
|
||||
binding.progressBar.visible(state.loadingState == LOADING)
|
||||
when (state.loadingState) {
|
||||
INITIAL, LOADING -> messageView.hide()
|
||||
INITIAL, LOADING -> binding.messageView.hide()
|
||||
ERROR_NETWORK -> {
|
||||
messageView.show()
|
||||
messageView.setup(R.drawable.elephant_offline, R.string.error_network) {
|
||||
binding.messageView.show()
|
||||
binding.messageView.setup(R.drawable.elephant_offline, R.string.error_network) {
|
||||
viewModel.retryLoading()
|
||||
}
|
||||
}
|
||||
ERROR_OTHER -> {
|
||||
messageView.show()
|
||||
messageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
binding.messageView.show()
|
||||
binding.messageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
viewModel.retryLoading()
|
||||
}
|
||||
}
|
||||
LOADED ->
|
||||
if (state.lists.isEmpty()) {
|
||||
messageView.show()
|
||||
messageView.setup(R.drawable.elephant_friend_empty, R.string.message_empty,
|
||||
binding.messageView.show()
|
||||
binding.messageView.setup(R.drawable.elephant_friend_empty, R.string.message_empty,
|
||||
null)
|
||||
} else {
|
||||
messageView.hide()
|
||||
binding.messageView.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showMessage(@StringRes messageId: Int) {
|
||||
Snackbar.make(
|
||||
listsRecycler, messageId, Snackbar.LENGTH_SHORT
|
||||
binding.listsRecycler, messageId, Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
|
||||
}
|
||||
|
||||
private fun onListSelected(listId: String) {
|
||||
|
@ -215,8 +209,6 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
|||
}
|
||||
}
|
||||
|
||||
override fun androidInjector() = dispatchingAndroidInjector
|
||||
|
||||
private object ListsDiffer : DiffUtil.ItemCallback<MastoList>() {
|
||||
override fun areItemsTheSame(oldItem: MastoList, newItem: MastoList): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
|
@ -273,4 +265,10 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
|||
viewModel.renameList(listId, name.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun androidInjector() = dispatchingAndroidInjector
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context) = Intent(context, ListsActivity::class.java)
|
||||
}
|
||||
}
|
|
@ -29,15 +29,12 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import com.bumptech.glide.Glide
|
||||
import com.keylesspalace.tusky.databinding.ActivityLoginBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.entity.AccessToken
|
||||
import com.keylesspalace.tusky.entity.AppCredentials
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.getNonNullString
|
||||
import com.keylesspalace.tusky.util.rickRoll
|
||||
import com.keylesspalace.tusky.util.shouldRickRoll
|
||||
import kotlinx.android.synthetic.main.activity_login.*
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import okhttp3.HttpUrl
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
|
@ -49,6 +46,8 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
@Inject
|
||||
lateinit var mastodonApi: MastodonApi
|
||||
|
||||
private val binding by viewBinding(ActivityLoginBinding::inflate)
|
||||
|
||||
private lateinit var preferences: SharedPreferences
|
||||
|
||||
private val oauthRedirectUri: String
|
||||
|
@ -61,26 +60,26 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_login)
|
||||
setContentView(binding.root)
|
||||
|
||||
if(savedInstanceState == null && BuildConfig.CUSTOM_INSTANCE.isNotBlank() && !isAdditionalLogin()) {
|
||||
domainEditText.setText(BuildConfig.CUSTOM_INSTANCE)
|
||||
domainEditText.setSelection(BuildConfig.CUSTOM_INSTANCE.length)
|
||||
binding.domainEditText.setText(BuildConfig.CUSTOM_INSTANCE)
|
||||
binding.domainEditText.setSelection(BuildConfig.CUSTOM_INSTANCE.length)
|
||||
}
|
||||
|
||||
if(BuildConfig.CUSTOM_LOGO_URL.isNotBlank()) {
|
||||
Glide.with(loginLogo)
|
||||
Glide.with(binding.loginLogo)
|
||||
.load(BuildConfig.CUSTOM_LOGO_URL)
|
||||
.placeholder(null)
|
||||
.into(loginLogo)
|
||||
.into(binding.loginLogo)
|
||||
}
|
||||
|
||||
preferences = getSharedPreferences(
|
||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE)
|
||||
|
||||
loginButton.setOnClickListener { onButtonClick() }
|
||||
binding.loginButton.setOnClickListener { onButtonClick() }
|
||||
|
||||
whatsAnInstanceTextView.setOnClickListener {
|
||||
binding.whatsAnInstanceTextView.setOnClickListener {
|
||||
val dialog = AlertDialog.Builder(this)
|
||||
.setMessage(R.string.dialog_whats_an_instance)
|
||||
.setPositiveButton(R.string.action_close, null)
|
||||
|
@ -90,11 +89,11 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
}
|
||||
|
||||
if (isAdditionalLogin()) {
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
} else {
|
||||
toolbar.visibility = View.GONE
|
||||
binding.toolbar.visibility = View.GONE
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,15 +116,15 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
*/
|
||||
private fun onButtonClick() {
|
||||
|
||||
loginButton.isEnabled = false
|
||||
binding.loginButton.isEnabled = false
|
||||
|
||||
val domain = canonicalizeDomain(domainEditText.text.toString())
|
||||
val domain = canonicalizeDomain(binding.domainEditText.text.toString())
|
||||
|
||||
try {
|
||||
HttpUrl.Builder().host(domain).scheme("https").build()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
setLoading(false)
|
||||
domainTextInputLayout.error = getString(R.string.error_invalid_domain)
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_invalid_domain)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -138,8 +137,8 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
override fun onResponse(call: Call<AppCredentials>,
|
||||
response: Response<AppCredentials>) {
|
||||
if (!response.isSuccessful) {
|
||||
loginButton.isEnabled = true
|
||||
domainTextInputLayout.error = getString(R.string.error_failed_app_registration)
|
||||
binding.loginButton.isEnabled = true
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_failed_app_registration)
|
||||
setLoading(false)
|
||||
Log.e(TAG, "App authentication failed. " + response.message())
|
||||
return
|
||||
|
@ -158,8 +157,8 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
}
|
||||
|
||||
override fun onFailure(call: Call<AppCredentials>, t: Throwable) {
|
||||
loginButton.isEnabled = true
|
||||
domainTextInputLayout.error = getString(R.string.error_failed_app_registration)
|
||||
binding.loginButton.isEnabled = true
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_failed_app_registration)
|
||||
setLoading(false)
|
||||
Log.e(TAG, Log.getStackTraceString(t))
|
||||
}
|
||||
|
@ -190,7 +189,7 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
if (viewIntent.resolveActivity(packageManager) != null) {
|
||||
startActivity(viewIntent)
|
||||
} else {
|
||||
domainEditText.error = getString(R.string.error_no_web_browser_found)
|
||||
binding.domainEditText.error = getString(R.string.error_no_web_browser_found)
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +223,7 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
onLoginSuccess(response.body()!!.accessToken, domain)
|
||||
} else {
|
||||
setLoading(false)
|
||||
domainTextInputLayout.error = getString(R.string.error_retrieving_oauth_token)
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_retrieving_oauth_token)
|
||||
Log.e(TAG, String.format("%s %s",
|
||||
getString(R.string.error_retrieving_oauth_token),
|
||||
response.message()))
|
||||
|
@ -233,7 +232,7 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
|
||||
override fun onFailure(call: Call<AccessToken>, t: Throwable) {
|
||||
setLoading(false)
|
||||
domainTextInputLayout.error = getString(R.string.error_retrieving_oauth_token)
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_retrieving_oauth_token)
|
||||
Log.e(TAG, String.format("%s %s",
|
||||
getString(R.string.error_retrieving_oauth_token),
|
||||
t.message))
|
||||
|
@ -246,14 +245,14 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
/* Authorization failed. Put the error response where the user can read it and they
|
||||
* can try again. */
|
||||
setLoading(false)
|
||||
domainTextInputLayout.error = getString(R.string.error_authorization_denied)
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_authorization_denied)
|
||||
Log.e(TAG, String.format("%s %s",
|
||||
getString(R.string.error_authorization_denied),
|
||||
error))
|
||||
} else {
|
||||
// This case means a junk response was received somehow.
|
||||
setLoading(false)
|
||||
domainTextInputLayout.error = getString(R.string.error_authorization_unknown)
|
||||
binding.domainTextInputLayout.error = getString(R.string.error_authorization_unknown)
|
||||
}
|
||||
} else {
|
||||
// first show or user cancelled login
|
||||
|
@ -263,12 +262,12 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
|
||||
private fun setLoading(loadingState: Boolean) {
|
||||
if (loadingState) {
|
||||
loginLoadingLayout.visibility = View.VISIBLE
|
||||
loginInputLayout.visibility = View.GONE
|
||||
binding.loginLoadingLayout.visibility = View.VISIBLE
|
||||
binding.loginInputLayout.visibility = View.GONE
|
||||
} else {
|
||||
loginLoadingLayout.visibility = View.GONE
|
||||
loginInputLayout.visibility = View.VISIBLE
|
||||
loginButton.isEnabled = true
|
||||
binding.loginLoadingLayout.visibility = View.GONE
|
||||
binding.loginInputLayout.visibility = View.VISIBLE
|
||||
binding.loginButton.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
|||
import com.keylesspalace.tusky.components.preference.PreferencesActivity
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
||||
import com.keylesspalace.tusky.components.search.SearchActivity
|
||||
import com.keylesspalace.tusky.databinding.ActivityMainBinding
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.db.AppDatabase
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
|
@ -86,7 +87,6 @@ import dagger.android.DispatchingAndroidInjector
|
|||
import dagger.android.HasAndroidInjector
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
||||
|
@ -108,6 +108,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
@Inject
|
||||
lateinit var draftHelper: DraftHelper
|
||||
|
||||
private val binding by viewBinding(ActivityMainBinding::inflate)
|
||||
|
||||
private lateinit var header: AccountHeaderView
|
||||
|
||||
private var notificationTabPosition = 0
|
||||
|
@ -179,21 +181,21 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
}
|
||||
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
|
||||
setContentView(R.layout.activity_main)
|
||||
setContentView(binding.root)
|
||||
|
||||
glide = Glide.with(this)
|
||||
|
||||
composeButton.setOnClickListener {
|
||||
binding.composeButton.setOnClickListener {
|
||||
val composeIntent = Intent(applicationContext, ComposeActivity::class.java)
|
||||
startActivity(composeIntent)
|
||||
}
|
||||
|
||||
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
||||
mainToolbar.visible(!hideTopToolbar)
|
||||
binding.mainToolbar.visible(!hideTopToolbar)
|
||||
|
||||
loadDrawerAvatar(activeAccount.profilePictureUrl, true)
|
||||
|
||||
mainToolbar.menu.add(R.string.action_search).apply {
|
||||
binding.mainToolbar.menu.add(R.string.action_search).apply {
|
||||
setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
icon = IconicsDrawable(this@MainActivity, GoogleMaterial.Icon.gmd_search).apply {
|
||||
sizeDp = 20
|
||||
|
@ -249,11 +251,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
|
||||
override fun onBackPressed() {
|
||||
when {
|
||||
mainDrawerLayout.isOpen -> {
|
||||
mainDrawerLayout.close()
|
||||
binding.mainDrawerLayout.isOpen -> {
|
||||
binding.mainDrawerLayout.close()
|
||||
}
|
||||
viewPager.currentItem != 0 -> {
|
||||
viewPager.currentItem = 0
|
||||
binding.viewPager.currentItem != 0 -> {
|
||||
binding.viewPager.currentItem = 0
|
||||
}
|
||||
else -> {
|
||||
super.onBackPressed()
|
||||
|
@ -264,10 +266,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_MENU -> {
|
||||
if (mainDrawerLayout.isOpen) {
|
||||
mainDrawerLayout.close()
|
||||
if (binding.mainDrawerLayout.isOpen) {
|
||||
binding.mainDrawerLayout.close()
|
||||
} else {
|
||||
mainDrawerLayout.open()
|
||||
binding.mainDrawerLayout.open()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -319,8 +321,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
|
||||
private fun setupDrawer(savedInstanceState: Bundle?, addSearchButton: Boolean) {
|
||||
|
||||
mainToolbar.setNavigationOnClickListener {
|
||||
mainDrawerLayout.open()
|
||||
binding.mainToolbar.setNavigationOnClickListener {
|
||||
binding.mainDrawerLayout.open()
|
||||
}
|
||||
|
||||
header = AccountHeaderView(this).apply {
|
||||
|
@ -333,7 +335,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
descriptionRes = R.string.add_account_description
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_add
|
||||
}, 0)
|
||||
attachToSliderView(mainDrawer)
|
||||
attachToSliderView(binding.mainDrawer)
|
||||
dividerBelowHeader = false
|
||||
closeDrawerOnProfileListClick = true
|
||||
}
|
||||
|
@ -369,7 +371,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
})
|
||||
|
||||
mainDrawer.apply {
|
||||
binding.mainDrawer.apply {
|
||||
tintStatusBar = true
|
||||
addItems(
|
||||
primaryDrawerItem {
|
||||
|
@ -464,7 +466,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
)
|
||||
|
||||
if (addSearchButton) {
|
||||
mainDrawer.addItemsAtPosition(4,
|
||||
binding.mainDrawer.addItemsAtPosition(4,
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_search
|
||||
iconicsIcon = GoogleMaterial.Icon.gmd_search
|
||||
|
@ -478,7 +480,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
mainDrawer.addItems(
|
||||
binding.mainDrawer.addItems(
|
||||
secondaryDrawerItem {
|
||||
nameText = "debug"
|
||||
isEnabled = false
|
||||
|
@ -490,7 +492,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(mainDrawer.saveInstanceState(outState))
|
||||
super.onSaveInstanceState(binding.mainDrawer.saveInstanceState(outState))
|
||||
}
|
||||
|
||||
private fun setupTabs(selectNotificationTab: Boolean) {
|
||||
|
@ -498,21 +500,21 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
val activeTabLayout = if (preferences.getString("mainNavPosition", "top") == "bottom") {
|
||||
val actionBarSize = ThemeUtils.getDimension(this, R.attr.actionBarSize)
|
||||
val fabMargin = resources.getDimensionPixelSize(R.dimen.fabMargin)
|
||||
(composeButton.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = actionBarSize + fabMargin
|
||||
tabLayout.hide()
|
||||
bottomTabLayout
|
||||
(binding.composeButton.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = actionBarSize + fabMargin
|
||||
binding.tabLayout.hide()
|
||||
binding.bottomTabLayout
|
||||
} else {
|
||||
bottomNav.hide()
|
||||
(viewPager.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 0
|
||||
(composeButton.layoutParams as CoordinatorLayout.LayoutParams).anchorId = R.id.viewPager
|
||||
tabLayout
|
||||
binding.bottomNav.hide()
|
||||
(binding.viewPager.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 0
|
||||
(binding.composeButton.layoutParams as CoordinatorLayout.LayoutParams).anchorId = R.id.viewPager
|
||||
binding.tabLayout
|
||||
}
|
||||
|
||||
val tabs = accountManager.activeAccount!!.tabPreferences
|
||||
|
||||
val adapter = MainPagerAdapter(tabs, this)
|
||||
viewPager.adapter = adapter
|
||||
TabLayoutMediator(activeTabLayout, viewPager) { _: TabLayout.Tab?, _: Int -> }.attach()
|
||||
binding.viewPager.adapter = adapter
|
||||
TabLayoutMediator(activeTabLayout, binding.viewPager) { _: TabLayout.Tab?, _: Int -> }.attach()
|
||||
activeTabLayout.removeAllTabs()
|
||||
for (i in tabs.indices) {
|
||||
val tab = activeTabLayout.newTab()
|
||||
|
@ -533,10 +535,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
|
||||
val pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
|
||||
viewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
||||
binding.viewPager.setPageTransformer(MarginPageTransformer(pageMargin))
|
||||
|
||||
val enableSwipeForTabs = preferences.getBoolean("enableSwipeForTabs", true)
|
||||
viewPager.isUserInputEnabled = enableSwipeForTabs
|
||||
binding.viewPager.isUserInputEnabled = enableSwipeForTabs
|
||||
|
||||
onTabSelectedListener?.let {
|
||||
activeTabLayout.removeOnTabSelectedListener(it)
|
||||
|
@ -548,7 +550,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
NotificationHelper.clearNotificationsForActiveAccount(this@MainActivity, accountManager)
|
||||
}
|
||||
|
||||
mainToolbar.title = tabs[tab.position].title(this@MainActivity)
|
||||
binding.mainToolbar.title = tabs[tab.position].title(this@MainActivity)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||
|
@ -564,8 +566,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
|
||||
val activeTabPosition = if (selectNotificationTab) notificationTabPosition else 0
|
||||
mainToolbar.title = tabs[activeTabPosition].title(this@MainActivity)
|
||||
mainToolbar.setOnClickListener {
|
||||
binding.mainToolbar.title = tabs[activeTabPosition].title(this@MainActivity)
|
||||
binding.mainToolbar.setOnClickListener {
|
||||
(adapter.getFragment(activeTabLayout.selectedTabPosition) as? ReselectableFragment)?.onReselect()
|
||||
}
|
||||
|
||||
|
@ -659,7 +661,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
NotificationHelper.createNotificationChannelsForAccount(accountManager.activeAccount!!, this)
|
||||
|
||||
// Show follow requests in the menu, if this is a locked account.
|
||||
if (me.locked && mainDrawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) {
|
||||
if (me.locked && binding.mainDrawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) {
|
||||
val followRequestsItem = primaryDrawerItem {
|
||||
identifier = DRAWER_ITEM_FOLLOW_REQUESTS
|
||||
nameRes = R.string.action_view_follow_requests
|
||||
|
@ -670,9 +672,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
startActivityWithSlideInAnimation(intent)
|
||||
}
|
||||
}
|
||||
mainDrawer.addItemAtPosition(4, followRequestsItem)
|
||||
binding.mainDrawer.addItemAtPosition(4, followRequestsItem)
|
||||
} else if (!me.locked) {
|
||||
mainDrawer.removeItems(DRAWER_ITEM_FOLLOW_REQUESTS)
|
||||
binding.mainDrawer.removeItems(DRAWER_ITEM_FOLLOW_REQUESTS)
|
||||
}
|
||||
updateProfiles()
|
||||
updateShortcut(this, accountManager.activeAccount!!)
|
||||
|
@ -695,16 +697,16 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
|
||||
override fun onLoadStarted(placeholder: Drawable?) {
|
||||
if (placeholder != null) {
|
||||
mainToolbar.navigationIcon = FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
||||
binding.mainToolbar.navigationIcon = FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
||||
}
|
||||
}
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
mainToolbar.navigationIcon = FixedSizeDrawable(resource, navIconSize, navIconSize)
|
||||
binding.mainToolbar.navigationIcon = FixedSizeDrawable(resource, navIconSize, navIconSize)
|
||||
}
|
||||
|
||||
override fun onLoadCleared(placeholder: Drawable?) {
|
||||
if (placeholder != null) {
|
||||
mainToolbar.navigationIcon = FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
||||
binding.mainToolbar.navigationIcon = FixedSizeDrawable(placeholder, navIconSize, navIconSize)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -726,7 +728,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
|
||||
private fun updateAnnouncementsBadge() {
|
||||
mainDrawer.updateBadge(DRAWER_ITEM_ANNOUNCEMENTS, StringHolder(if (unreadAnnouncementsCount <= 0) null else unreadAnnouncementsCount.toString()))
|
||||
binding.mainDrawer.updateBadge(DRAWER_ITEM_ANNOUNCEMENTS, StringHolder(if (unreadAnnouncementsCount <= 0) null else unreadAnnouncementsCount.toString()))
|
||||
}
|
||||
|
||||
private fun updateProfiles() {
|
||||
|
@ -779,7 +781,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
|
||||
}
|
||||
|
||||
override fun getActionButton(): FloatingActionButton? = composeButton
|
||||
override fun getActionButton(): FloatingActionButton? = binding.composeButton
|
||||
|
||||
override fun androidInjector() = androidInjector
|
||||
|
||||
|
|
|
@ -4,43 +4,28 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.keylesspalace.tusky.databinding.ActivityModalTimelineBinding
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment
|
||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
||||
|
||||
companion object {
|
||||
private const val ARG_KIND = "kind"
|
||||
private const val ARG_ARG = "arg"
|
||||
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context, kind: TimelineFragment.Kind,
|
||||
argument: String?): Intent {
|
||||
val intent = Intent(context, ModalTimelineActivity::class.java)
|
||||
intent.putExtra(ARG_KIND, kind)
|
||||
intent.putExtra(ARG_ARG, argument)
|
||||
return intent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_modal_timeline)
|
||||
val binding = ActivityModalTimelineBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
val bar = supportActionBar
|
||||
if (bar != null) {
|
||||
bar.title = getString(R.string.title_list_timeline)
|
||||
bar.setDisplayHomeAsUpEnabled(true)
|
||||
bar.setDisplayShowHomeEnabled(true)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.apply {
|
||||
title = getString(R.string.title_list_timeline)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
if (supportFragmentManager.findFragmentById(R.id.contentFrame) == null) {
|
||||
|
@ -57,4 +42,18 @@ class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAn
|
|||
|
||||
override fun androidInjector() = dispatchingAndroidInjector
|
||||
|
||||
companion object {
|
||||
private const val ARG_KIND = "kind"
|
||||
private const val ARG_ARG = "arg"
|
||||
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context, kind: TimelineFragment.Kind,
|
||||
argument: String?): Intent {
|
||||
val intent = Intent(context, ModalTimelineActivity::class.java)
|
||||
intent.putExtra(ARG_KIND, kind)
|
||||
intent.putExtra(ARG_ARG, argument)
|
||||
return intent
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.commit
|
||||
import com.keylesspalace.tusky.databinding.ActivityStatuslistBinding
|
||||
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment
|
||||
import com.keylesspalace.tusky.fragment.TimelineFragment.Kind
|
||||
|
@ -27,9 +28,6 @@ import javax.inject.Inject
|
|||
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.extensions.CacheImplementation
|
||||
import kotlinx.android.extensions.ContainerOptions
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
|
||||
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||
|
||||
|
@ -39,12 +37,12 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
private val kind: Kind
|
||||
get() = Kind.valueOf(intent.getStringExtra(EXTRA_KIND)!!)
|
||||
|
||||
@ContainerOptions(cache = CacheImplementation.NO_CACHE)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_statuslist)
|
||||
val binding = ActivityStatuslistBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
|
||||
val title = if(kind == Kind.FAVOURITES) {
|
||||
R.string.title_favourites
|
||||
|
|
|
@ -38,17 +38,17 @@ import com.keylesspalace.tusky.adapter.ListSelectionAdapter
|
|||
import com.keylesspalace.tusky.adapter.TabAdapter
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
|
||||
import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.onTextChanged
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import com.keylesspalace.tusky.util.visible
|
||||
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from
|
||||
import com.uber.autodispose.autoDispose
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.activity_tab_preference.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import java.util.regex.Pattern
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -59,6 +59,8 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
private val binding by viewBinding(ActivityTabPreferenceBinding::inflate)
|
||||
|
||||
private lateinit var currentTabs: MutableList<TabData>
|
||||
private lateinit var currentTabsAdapter: TabAdapter
|
||||
private lateinit var touchHelper: ItemTouchHelper
|
||||
|
@ -73,9 +75,9 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_tab_preference)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
|
||||
supportActionBar?.apply {
|
||||
setTitle(R.string.title_tab_preferences)
|
||||
|
@ -85,13 +87,13 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
|
||||
currentTabs = accountManager.activeAccount?.tabPreferences.orEmpty().toMutableList()
|
||||
currentTabsAdapter = TabAdapter(currentTabs, false, this, currentTabs.size <= MIN_TAB_COUNT)
|
||||
currentTabsRecyclerView.adapter = currentTabsAdapter
|
||||
currentTabsRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
currentTabsRecyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
|
||||
binding.currentTabsRecyclerView.adapter = currentTabsAdapter
|
||||
binding.currentTabsRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.currentTabsRecyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
|
||||
|
||||
addTabAdapter = TabAdapter(listOf(createTabDataFromId(DIRECT)), true, this)
|
||||
addTabRecyclerView.adapter = addTabAdapter
|
||||
addTabRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
binding.addTabRecyclerView.adapter = addTabAdapter
|
||||
binding.addTabRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
|
||||
touchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
|
||||
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
|
||||
|
@ -132,17 +134,17 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
}
|
||||
})
|
||||
|
||||
touchHelper.attachToRecyclerView(currentTabsRecyclerView)
|
||||
touchHelper.attachToRecyclerView(binding.currentTabsRecyclerView)
|
||||
|
||||
actionButton.setOnClickListener {
|
||||
binding.actionButton.setOnClickListener {
|
||||
toggleFab(true)
|
||||
}
|
||||
|
||||
scrim.setOnClickListener {
|
||||
binding.scrim.setOnClickListener {
|
||||
toggleFab(false)
|
||||
}
|
||||
|
||||
maxTabsInfo.text = getString(R.string.max_tab_number_reached, MAX_TAB_COUNT)
|
||||
binding.maxTabsInfo.text = getString(R.string.max_tab_number_reached, MAX_TAB_COUNT)
|
||||
|
||||
updateAvailableTabs()
|
||||
}
|
||||
|
@ -193,18 +195,18 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
|
||||
private fun toggleFab(expand: Boolean) {
|
||||
val transition = MaterialContainerTransform().apply {
|
||||
startView = if (expand) actionButton else sheet
|
||||
val endView: View = if (expand) sheet else actionButton
|
||||
startView = if (expand) binding.actionButton else binding.sheet
|
||||
val endView: View = if (expand) binding.sheet else binding.actionButton
|
||||
this.endView = endView
|
||||
addTarget(endView)
|
||||
scrimColor = Color.TRANSPARENT
|
||||
setPathMotion(MaterialArcMotion())
|
||||
}
|
||||
|
||||
TransitionManager.beginDelayedTransition(tabPreferenceContainer, transition)
|
||||
actionButton.visible(!expand)
|
||||
sheet.visible(expand)
|
||||
scrim.visible(expand)
|
||||
TransitionManager.beginDelayedTransition(binding.root, transition)
|
||||
binding.actionButton.visible(!expand)
|
||||
binding.sheet.visible(expand)
|
||||
binding.scrim.visible(expand)
|
||||
}
|
||||
|
||||
private fun showAddHashtagDialog(tab: TabData? = null, tabPosition: Int = 0) {
|
||||
|
@ -310,7 +312,7 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
|
||||
addTabAdapter.updateData(addableTabs)
|
||||
|
||||
maxTabsInfo.visible(addableTabs.size == 0 || currentTabs.size >= MAX_TAB_COUNT)
|
||||
binding.maxTabsInfo.visible(addableTabs.size == 0 || currentTabs.size >= MAX_TAB_COUNT)
|
||||
currentTabsAdapter.setRemoveButtonVisible(currentTabs.size > MIN_TAB_COUNT)
|
||||
}
|
||||
|
||||
|
@ -337,7 +339,7 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
|||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (actionButton.isVisible) {
|
||||
if (binding.actionButton.isVisible) {
|
||||
super.onBackPressed()
|
||||
} else {
|
||||
toggleFab(false)
|
||||
|
|
|
@ -44,18 +44,19 @@ import androidx.viewpager2.widget.ViewPager2
|
|||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.FutureTarget
|
||||
import com.keylesspalace.tusky.BuildConfig.APPLICATION_ID
|
||||
import com.keylesspalace.tusky.databinding.ActivityViewMediaBinding
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.fragment.ViewImageFragment
|
||||
import com.keylesspalace.tusky.pager.SingleImagePagerAdapter
|
||||
import com.keylesspalace.tusky.pager.ImagePagerAdapter
|
||||
import com.keylesspalace.tusky.util.getTemporaryMediaFilename
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import com.keylesspalace.tusky.viewdata.AttachmentViewData
|
||||
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
|
||||
import com.uber.autodispose.autoDispose
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.activity_view_media.*
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
|
@ -65,27 +66,8 @@ import java.util.*
|
|||
typealias ToolbarVisibilityListener = (isVisible: Boolean) -> Unit
|
||||
|
||||
class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener {
|
||||
companion object {
|
||||
private const val EXTRA_ATTACHMENTS = "attachments"
|
||||
private const val EXTRA_ATTACHMENT_INDEX = "index"
|
||||
private const val EXTRA_SINGLE_IMAGE_URL = "single_image"
|
||||
private const val TAG = "ViewMediaActivity"
|
||||
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context?, attachments: List<AttachmentViewData>, index: Int): Intent {
|
||||
val intent = Intent(context, ViewMediaActivity::class.java)
|
||||
intent.putParcelableArrayListExtra(EXTRA_ATTACHMENTS, ArrayList(attachments))
|
||||
intent.putExtra(EXTRA_ATTACHMENT_INDEX, index)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newSingleImageIntent(context: Context, url: String): Intent {
|
||||
val intent = Intent(context, ViewMediaActivity::class.java)
|
||||
intent.putExtra(EXTRA_SINGLE_IMAGE_URL, url)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
private val binding by viewBinding(ActivityViewMediaBinding::inflate)
|
||||
|
||||
var isToolbarVisible = true
|
||||
private set
|
||||
|
@ -102,7 +84,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_view_media)
|
||||
setContentView(binding.root)
|
||||
|
||||
supportPostponeEnterTransition()
|
||||
|
||||
|
@ -125,24 +107,24 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
SingleImagePagerAdapter(this, imageUrl!!)
|
||||
}
|
||||
|
||||
viewPager.adapter = adapter
|
||||
viewPager.setCurrentItem(initialPosition, false)
|
||||
viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() {
|
||||
binding.viewPager.adapter = adapter
|
||||
binding.viewPager.setCurrentItem(initialPosition, false)
|
||||
binding.viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
toolbar.title = getPageTitle(position)
|
||||
binding.toolbar.title = getPageTitle(position)
|
||||
}
|
||||
})
|
||||
|
||||
// Setup the toolbar.
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
val actionBar = supportActionBar
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
actionBar.setDisplayShowHomeEnabled(true)
|
||||
actionBar.title = getPageTitle(initialPosition)
|
||||
}
|
||||
toolbar.setNavigationOnClickListener { supportFinishAfterTransition() }
|
||||
toolbar.setOnMenuItemClickListener { item: MenuItem ->
|
||||
binding.toolbar.setNavigationOnClickListener { supportFinishAfterTransition() }
|
||||
binding.toolbar.setOnMenuItemClickListener { item: MenuItem ->
|
||||
when (item.itemId) {
|
||||
R.id.action_download -> requestDownloadMedia()
|
||||
R.id.action_open_status -> onOpenStatus()
|
||||
|
@ -156,7 +138,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
window.statusBarColor = Color.BLACK
|
||||
window.sharedElementEnterTransition.addListener(object : NoopTransitionListener {
|
||||
override fun onTransitionEnd(transition: Transition) {
|
||||
adapter.onTransitionEnd(viewPager.currentItem)
|
||||
adapter.onTransitionEnd(binding.viewPager.currentItem)
|
||||
window.sharedElementEnterTransition.removeListener(this)
|
||||
}
|
||||
})
|
||||
|
@ -165,7 +147,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.view_media_toolbar, menu)
|
||||
// We don't support 'open status' from single image views
|
||||
menu?.findItem(R.id.action_open_status)?.isVisible = (attachments != null)
|
||||
menu.findItem(R.id.action_open_status)?.isVisible = (attachments != null)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -192,14 +174,14 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
val alpha = if (isToolbarVisible) 1.0f else 0.0f
|
||||
if (isToolbarVisible) {
|
||||
// If to be visible, need to make visible immediately and animate alpha
|
||||
toolbar.alpha = 0.0f
|
||||
toolbar.visibility = visibility
|
||||
binding.toolbar.alpha = 0.0f
|
||||
binding.toolbar.visibility = visibility
|
||||
}
|
||||
|
||||
toolbar.animate().alpha(alpha)
|
||||
binding.toolbar.animate().alpha(alpha)
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
toolbar.visibility = visibility
|
||||
binding.toolbar.visibility = visibility
|
||||
animation.removeListener(this)
|
||||
}
|
||||
})
|
||||
|
@ -214,7 +196,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
}
|
||||
|
||||
private fun downloadMedia() {
|
||||
val url = imageUrl ?: attachments!![viewPager.currentItem].attachment.url
|
||||
val url = imageUrl ?: attachments!![binding.viewPager.currentItem].attachment.url
|
||||
val filename = Uri.parse(url).lastPathSegment
|
||||
Toast.makeText(applicationContext, resources.getString(R.string.download_image, filename), Toast.LENGTH_SHORT).show()
|
||||
|
||||
|
@ -230,18 +212,18 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
downloadMedia()
|
||||
} else {
|
||||
showErrorDialog(toolbar, R.string.error_media_download_permission, R.string.action_retry) { requestDownloadMedia() }
|
||||
showErrorDialog(binding.toolbar, R.string.error_media_download_permission, R.string.action_retry) { requestDownloadMedia() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onOpenStatus() {
|
||||
val attach = attachments!![viewPager.currentItem]
|
||||
val attach = attachments!![binding.viewPager.currentItem]
|
||||
startActivityWithSlideInAnimation(ViewThreadActivity.startIntent(this, attach.statusId, attach.statusUrl))
|
||||
}
|
||||
|
||||
private fun copyLink() {
|
||||
val url = imageUrl ?: attachments!![viewPager.currentItem].attachment.url
|
||||
val url = imageUrl ?: attachments!![binding.viewPager.currentItem].attachment.url
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(null, url))
|
||||
}
|
||||
|
@ -256,7 +238,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
if (imageUrl != null) {
|
||||
shareImage(directory, imageUrl!!)
|
||||
} else {
|
||||
val attachment = attachments!![viewPager.currentItem].attachment
|
||||
val attachment = attachments!![binding.viewPager.currentItem].attachment
|
||||
when (attachment.type) {
|
||||
Attachment.Type.IMAGE -> shareImage(directory, attachment.url)
|
||||
Attachment.Type.AUDIO,
|
||||
|
@ -280,7 +262,7 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
|
||||
private fun shareImage(directory: File, url: String) {
|
||||
isCreating = true
|
||||
progressBarShare.visibility = View.VISIBLE
|
||||
binding.progressBarShare.visibility = View.VISIBLE
|
||||
invalidateOptionsMenu()
|
||||
val file = File(directory, getTemporaryMediaFilename("png"))
|
||||
val futureTask: FutureTarget<Bitmap> =
|
||||
|
@ -312,14 +294,14 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
Log.d(TAG, "Download image result: $result")
|
||||
isCreating = false
|
||||
invalidateOptionsMenu()
|
||||
progressBarShare.visibility = View.GONE
|
||||
binding.progressBarShare.visibility = View.GONE
|
||||
if (result)
|
||||
shareFile(file, "image/png")
|
||||
},
|
||||
{ error ->
|
||||
isCreating = false
|
||||
invalidateOptionsMenu()
|
||||
progressBarShare.visibility = View.GONE
|
||||
binding.progressBarShare.visibility = View.GONE
|
||||
Log.e(TAG, "Failed to download image", error)
|
||||
}
|
||||
)
|
||||
|
@ -342,6 +324,28 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
|||
|
||||
shareFile(file, mimeType)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_ATTACHMENTS = "attachments"
|
||||
private const val EXTRA_ATTACHMENT_INDEX = "index"
|
||||
private const val EXTRA_SINGLE_IMAGE_URL = "single_image"
|
||||
private const val TAG = "ViewMediaActivity"
|
||||
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context?, attachments: List<AttachmentViewData>, index: Int): Intent {
|
||||
val intent = Intent(context, ViewMediaActivity::class.java)
|
||||
intent.putParcelableArrayListExtra(EXTRA_ATTACHMENTS, ArrayList(attachments))
|
||||
intent.putExtra(EXTRA_ATTACHMENT_INDEX, index)
|
||||
return intent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newSingleImageIntent(context: Context, url: String): Intent {
|
||||
val intent = Intent(context, ViewMediaActivity::class.java)
|
||||
intent.putExtra(EXTRA_SINGLE_IMAGE_URL, url)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ViewMediaAdapter(activity: FragmentActivity): FragmentStateAdapter(activity) {
|
||||
|
|
|
@ -30,13 +30,12 @@ import com.keylesspalace.tusky.R
|
|||
import com.keylesspalace.tusky.ViewTagActivity
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter
|
||||
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
||||
import com.keylesspalace.tusky.databinding.ActivityAnnouncementsBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.keylesspalace.tusky.view.EmojiPicker
|
||||
import kotlinx.android.synthetic.main.activity_announcements.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable {
|
||||
|
@ -46,6 +45,8 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
|||
|
||||
private val viewModel: AnnouncementsViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivityAnnouncementsBinding::inflate)
|
||||
|
||||
private lateinit var adapter: AnnouncementAdapter
|
||||
|
||||
private val picker by lazy { EmojiPicker(this) }
|
||||
|
@ -63,22 +64,22 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_announcements)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.apply {
|
||||
title = getString(R.string.title_announcements)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this::refreshAnnouncements)
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this::refreshAnnouncements)
|
||||
binding.swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
|
||||
announcementsList.setHasFixedSize(true)
|
||||
announcementsList.layoutManager = LinearLayoutManager(this)
|
||||
binding.announcementsList.setHasFixedSize(true)
|
||||
binding.announcementsList.layoutManager = LinearLayoutManager(this)
|
||||
val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
|
||||
announcementsList.addItemDecoration(divider)
|
||||
binding.announcementsList.addItemDecoration(divider)
|
||||
|
||||
val preferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val wellbeingEnabled = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
|
||||
|
@ -86,31 +87,31 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
|||
|
||||
adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis)
|
||||
|
||||
announcementsList.adapter = adapter
|
||||
binding.announcementsList.adapter = adapter
|
||||
|
||||
viewModel.announcements.observe(this) {
|
||||
when (it) {
|
||||
is Success -> {
|
||||
progressBar.hide()
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
binding.progressBar.hide()
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
if (it.data.isNullOrEmpty()) {
|
||||
errorMessageView.setup(R.drawable.elephant_friend_empty, R.string.no_announcements)
|
||||
errorMessageView.show()
|
||||
binding.errorMessageView.setup(R.drawable.elephant_friend_empty, R.string.no_announcements)
|
||||
binding.errorMessageView.show()
|
||||
} else {
|
||||
errorMessageView.hide()
|
||||
binding.errorMessageView.hide()
|
||||
}
|
||||
adapter.updateList(it.data ?: listOf())
|
||||
}
|
||||
is Loading -> {
|
||||
errorMessageView.hide()
|
||||
binding.errorMessageView.hide()
|
||||
}
|
||||
is Error -> {
|
||||
progressBar.hide()
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
errorMessageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
binding.progressBar.hide()
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
binding.errorMessageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
refreshAnnouncements()
|
||||
}
|
||||
errorMessageView.show()
|
||||
binding.errorMessageView.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,12 +121,12 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
|||
}
|
||||
|
||||
viewModel.load()
|
||||
progressBar.show()
|
||||
binding.progressBar.show()
|
||||
}
|
||||
|
||||
private fun refreshAnnouncements() {
|
||||
viewModel.load()
|
||||
swipeRefreshLayout.isRefreshing = true
|
||||
binding.swipeRefreshLayout.isRefreshing = true
|
||||
}
|
||||
|
||||
override fun openReactionPicker(announcementId: String, target: View) {
|
||||
|
|
|
@ -61,6 +61,7 @@ import com.keylesspalace.tusky.components.compose.dialog.makeCaptionDialog
|
|||
import com.keylesspalace.tusky.components.compose.dialog.showAddPollDialog
|
||||
import com.keylesspalace.tusky.components.compose.view.ComposeOptionsListener
|
||||
import com.keylesspalace.tusky.components.compose.view.ComposeScheduleView
|
||||
import com.keylesspalace.tusky.databinding.ActivityComposeBinding
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.db.DraftAttachment
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
|
@ -76,7 +77,6 @@ import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
|||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.activity_compose.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
@ -109,17 +109,20 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private val viewModel: ComposeViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivityComposeBinding::inflate)
|
||||
|
||||
private val maxUploadMediaNumber = 4
|
||||
private var mediaCount = 0
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT)
|
||||
if (theme == "black") {
|
||||
setTheme(R.style.TuskyDialogActivityBlackTheme)
|
||||
}
|
||||
setContentView(R.layout.activity_compose)
|
||||
setContentView(binding.root)
|
||||
|
||||
setupActionBar()
|
||||
// do not do anything when not logged in, activity will be finished in super.onCreate() anyway
|
||||
|
@ -135,10 +138,10 @@ class ComposeActivity : BaseActivity(),
|
|||
},
|
||||
onRemove = this::removeMediaFromQueue
|
||||
)
|
||||
composeMediaPreviewBar.layoutManager =
|
||||
binding.composeMediaPreviewBar.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||
composeMediaPreviewBar.adapter = mediaAdapter
|
||||
composeMediaPreviewBar.itemAnimator = null
|
||||
binding.composeMediaPreviewBar.adapter = mediaAdapter
|
||||
binding.composeMediaPreviewBar.itemAnimator = null
|
||||
|
||||
subscribeToUpdates(mediaAdapter)
|
||||
setupButtons()
|
||||
|
@ -154,11 +157,11 @@ class ComposeActivity : BaseActivity(),
|
|||
setupReplyViews(composeOptions?.replyingStatusAuthor, composeOptions?.replyingStatusContent)
|
||||
val tootText = composeOptions?.tootText
|
||||
if (!tootText.isNullOrEmpty()) {
|
||||
composeEditField.setText(tootText)
|
||||
binding.composeEditField.setText(tootText)
|
||||
}
|
||||
|
||||
if (!composeOptions?.scheduledAt.isNullOrEmpty()) {
|
||||
composeScheduleView.setDateTime(composeOptions?.scheduledAt)
|
||||
binding.composeScheduleView.setDateTime(composeOptions?.scheduledAt)
|
||||
}
|
||||
|
||||
setupComposeField(preferences, viewModel.startingText)
|
||||
|
@ -198,14 +201,14 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
if (shareBody.isNotBlank()) {
|
||||
val start = composeEditField.selectionStart.coerceAtLeast(0)
|
||||
val end = composeEditField.selectionEnd.coerceAtLeast(0)
|
||||
val start = binding.composeEditField.selectionStart.coerceAtLeast(0)
|
||||
val end = binding.composeEditField.selectionEnd.coerceAtLeast(0)
|
||||
val left = min(start, end)
|
||||
val right = max(start, end)
|
||||
composeEditField.text.replace(left, right, shareBody, 0, shareBody.length)
|
||||
binding.composeEditField.text.replace(left, right, shareBody, 0, shareBody.length)
|
||||
// move edittext cursor to first when shareBody parsed
|
||||
composeEditField.text.insert(0, "\n")
|
||||
composeEditField.setSelection(0)
|
||||
binding.composeEditField.text.insert(0, "\n")
|
||||
binding.composeEditField.setSelection(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,58 +217,58 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun setupReplyViews(replyingStatusAuthor: String?, replyingStatusContent: String?) {
|
||||
if (replyingStatusAuthor != null) {
|
||||
composeReplyView.show()
|
||||
composeReplyView.text = getString(R.string.replying_to, replyingStatusAuthor)
|
||||
binding.composeReplyView.show()
|
||||
binding.composeReplyView.text = getString(R.string.replying_to, replyingStatusAuthor)
|
||||
val arrowDownIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_down).apply { sizeDp = 12 }
|
||||
|
||||
ThemeUtils.setDrawableTint(this, arrowDownIcon, android.R.attr.textColorTertiary)
|
||||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
binding.composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
|
||||
composeReplyView.setOnClickListener {
|
||||
TransitionManager.beginDelayedTransition(composeReplyContentView.parent as ViewGroup)
|
||||
binding.composeReplyView.setOnClickListener {
|
||||
TransitionManager.beginDelayedTransition(binding.composeReplyContentView.parent as ViewGroup)
|
||||
|
||||
if (composeReplyContentView.isVisible) {
|
||||
composeReplyContentView.hide()
|
||||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
if (binding.composeReplyContentView.isVisible) {
|
||||
binding.composeReplyContentView.hide()
|
||||
binding.composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowDownIcon, null)
|
||||
} else {
|
||||
composeReplyContentView.show()
|
||||
binding.composeReplyContentView.show()
|
||||
val arrowUpIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_drop_up).apply { sizeDp = 12 }
|
||||
|
||||
ThemeUtils.setDrawableTint(this, arrowUpIcon, android.R.attr.textColorTertiary)
|
||||
composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowUpIcon, null)
|
||||
binding.composeReplyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, arrowUpIcon, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
replyingStatusContent?.let { composeReplyContentView.text = it }
|
||||
replyingStatusContent?.let { binding.composeReplyContentView.text = it }
|
||||
}
|
||||
|
||||
private fun setupContentWarningField(startingContentWarning: String?) {
|
||||
if (startingContentWarning != null) {
|
||||
composeContentWarningField.setText(startingContentWarning)
|
||||
binding.composeContentWarningField.setText(startingContentWarning)
|
||||
}
|
||||
composeContentWarningField.onTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
|
||||
binding.composeContentWarningField.onTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
|
||||
}
|
||||
|
||||
private fun setupComposeField(preferences: SharedPreferences, startingText: String?) {
|
||||
composeEditField.setOnCommitContentListener(this)
|
||||
binding.composeEditField.setOnCommitContentListener(this)
|
||||
|
||||
composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
|
||||
binding.composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
|
||||
|
||||
composeEditField.setAdapter(
|
||||
binding.composeEditField.setAdapter(
|
||||
ComposeAutoCompleteAdapter(
|
||||
this,
|
||||
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false),
|
||||
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
|
||||
)
|
||||
)
|
||||
composeEditField.setTokenizer(ComposeTokenizer())
|
||||
binding.composeEditField.setTokenizer(ComposeTokenizer())
|
||||
|
||||
composeEditField.setText(startingText)
|
||||
composeEditField.setSelection(composeEditField.length())
|
||||
binding.composeEditField.setText(startingText)
|
||||
binding.composeEditField.setSelection(binding.composeEditField.length())
|
||||
|
||||
val mentionColour = composeEditField.linkTextColors.defaultColor
|
||||
highlightSpans(composeEditField.text, mentionColour)
|
||||
composeEditField.afterTextChanged { editable ->
|
||||
val mentionColour = binding.composeEditField.linkTextColors.defaultColor
|
||||
highlightSpans(binding.composeEditField.text, mentionColour)
|
||||
binding.composeEditField.afterTextChanged { editable ->
|
||||
highlightSpans(editable, mentionColour)
|
||||
updateVisibleCharactersLeft()
|
||||
}
|
||||
|
@ -273,7 +276,7 @@ class ComposeActivity : BaseActivity(),
|
|||
// work around Android platform bug -> https://issuetracker.google.com/issues/67102093
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O
|
||||
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
|
||||
composeEditField.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
|
||||
binding.composeEditField.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +285,7 @@ class ComposeActivity : BaseActivity(),
|
|||
viewModel.instanceParams.observe { instanceData ->
|
||||
maximumTootCharacters = instanceData.maxChars
|
||||
updateVisibleCharactersLeft()
|
||||
composeScheduleButton.visible(instanceData.supportsScheduled)
|
||||
binding.composeScheduleButton.visible(instanceData.supportsScheduled)
|
||||
}
|
||||
viewModel.emoji.observe { emoji -> setEmojiList(emoji) }
|
||||
combineLiveData(viewModel.markMediaAsSensitive, viewModel.showContentWarning) { markSensitive, showContentWarning ->
|
||||
|
@ -296,19 +299,19 @@ class ComposeActivity : BaseActivity(),
|
|||
mediaAdapter.submitList(media)
|
||||
if (media.size != mediaCount) {
|
||||
mediaCount = media.size
|
||||
composeMediaPreviewBar.visible(media.isNotEmpty())
|
||||
binding.composeMediaPreviewBar.visible(media.isNotEmpty())
|
||||
updateSensitiveMediaToggle(viewModel.markMediaAsSensitive.value != false, viewModel.showContentWarning.value != false)
|
||||
}
|
||||
}
|
||||
viewModel.poll.observe { poll ->
|
||||
pollPreview.visible(poll != null)
|
||||
poll?.let(pollPreview::setPoll)
|
||||
binding.pollPreview.visible(poll != null)
|
||||
poll?.let(binding.pollPreview::setPoll)
|
||||
}
|
||||
viewModel.scheduledAt.observe { scheduledAt ->
|
||||
if (scheduledAt == null) {
|
||||
composeScheduleView.resetSchedule()
|
||||
binding.composeScheduleView.resetSchedule()
|
||||
} else {
|
||||
composeScheduleView.setDateTime(scheduledAt)
|
||||
binding.composeScheduleView.setDateTime(scheduledAt)
|
||||
}
|
||||
updateScheduleButton()
|
||||
}
|
||||
|
@ -316,7 +319,7 @@ class ComposeActivity : BaseActivity(),
|
|||
val active = poll == null
|
||||
&& media!!.size != 4
|
||||
&& (media.isEmpty() || media.first().type == QueuedMedia.Type.IMAGE)
|
||||
enableButton(composeAddMediaButton, active, active)
|
||||
enableButton(binding.composeAddMediaButton, active, active)
|
||||
enablePollButton(media.isNullOrEmpty())
|
||||
}.subscribe()
|
||||
viewModel.uploadError.observe {
|
||||
|
@ -324,52 +327,52 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
viewModel.setupComplete.observe {
|
||||
// Focus may have changed during view model setup, ensure initial focus is on the edit field
|
||||
composeEditField.requestFocus()
|
||||
binding.composeEditField.requestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupButtons() {
|
||||
composeOptionsBottomSheet.listener = this
|
||||
binding.composeOptionsBottomSheet.listener = this
|
||||
|
||||
composeOptionsBehavior = BottomSheetBehavior.from(composeOptionsBottomSheet)
|
||||
addMediaBehavior = BottomSheetBehavior.from(addMediaBottomSheet)
|
||||
scheduleBehavior = BottomSheetBehavior.from(composeScheduleView)
|
||||
emojiBehavior = BottomSheetBehavior.from(emojiView)
|
||||
composeOptionsBehavior = BottomSheetBehavior.from(binding.composeOptionsBottomSheet)
|
||||
addMediaBehavior = BottomSheetBehavior.from(binding.addMediaBottomSheet)
|
||||
scheduleBehavior = BottomSheetBehavior.from(binding.composeScheduleView)
|
||||
emojiBehavior = BottomSheetBehavior.from(binding.emojiView)
|
||||
|
||||
enableButton(composeEmojiButton, clickable = false, colorActive = false)
|
||||
enableButton(binding.composeEmojiButton, clickable = false, colorActive = false)
|
||||
|
||||
// Setup the interface buttons.
|
||||
composeTootButton.setOnClickListener { onSendClicked() }
|
||||
composeAddMediaButton.setOnClickListener { openPickDialog() }
|
||||
composeToggleVisibilityButton.setOnClickListener { showComposeOptions() }
|
||||
composeContentWarningButton.setOnClickListener { onContentWarningChanged() }
|
||||
composeEmojiButton.setOnClickListener { showEmojis() }
|
||||
composeHideMediaButton.setOnClickListener { toggleHideMedia() }
|
||||
composeScheduleButton.setOnClickListener { onScheduleClick() }
|
||||
composeScheduleView.setResetOnClickListener { resetSchedule() }
|
||||
composeScheduleView.setListener(this)
|
||||
atButton.setOnClickListener { atButtonClicked() }
|
||||
hashButton.setOnClickListener { hashButtonClicked() }
|
||||
binding.composeTootButton.setOnClickListener { onSendClicked() }
|
||||
binding.composeAddMediaButton.setOnClickListener { openPickDialog() }
|
||||
binding.composeToggleVisibilityButton.setOnClickListener { showComposeOptions() }
|
||||
binding.composeContentWarningButton.setOnClickListener { onContentWarningChanged() }
|
||||
binding.composeEmojiButton.setOnClickListener { showEmojis() }
|
||||
binding.composeHideMediaButton.setOnClickListener { toggleHideMedia() }
|
||||
binding.composeScheduleButton.setOnClickListener { onScheduleClick() }
|
||||
binding.composeScheduleView.setResetOnClickListener { resetSchedule() }
|
||||
binding.composeScheduleView.setListener(this)
|
||||
binding.atButton.setOnClickListener { atButtonClicked() }
|
||||
binding.hashButton.setOnClickListener { hashButtonClicked() }
|
||||
|
||||
val textColor = ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
|
||||
val cameraIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_camera_alt).apply { colorInt = textColor; sizeDp = 18 }
|
||||
actionPhotoTake.setCompoundDrawablesRelativeWithIntrinsicBounds(cameraIcon, null, null, null)
|
||||
binding.actionPhotoTake.setCompoundDrawablesRelativeWithIntrinsicBounds(cameraIcon, null, null, null)
|
||||
|
||||
val imageIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_image).apply { colorInt = textColor; sizeDp = 18 }
|
||||
actionPhotoPick.setCompoundDrawablesRelativeWithIntrinsicBounds(imageIcon, null, null, null)
|
||||
binding.actionPhotoPick.setCompoundDrawablesRelativeWithIntrinsicBounds(imageIcon, null, null, null)
|
||||
|
||||
val pollIcon = IconicsDrawable(this, GoogleMaterial.Icon.gmd_poll).apply { colorInt = textColor; sizeDp = 18 }
|
||||
addPollTextActionTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(pollIcon, null, null, null)
|
||||
binding.addPollTextActionTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(pollIcon, null, null, null)
|
||||
|
||||
actionPhotoTake.setOnClickListener { initiateCameraApp() }
|
||||
actionPhotoPick.setOnClickListener { onMediaPick() }
|
||||
addPollTextActionTextView.setOnClickListener { openPollDialog() }
|
||||
binding.actionPhotoTake.setOnClickListener { initiateCameraApp() }
|
||||
binding.actionPhotoPick.setOnClickListener { onMediaPick() }
|
||||
binding.addPollTextActionTextView.setOnClickListener { openPollDialog() }
|
||||
}
|
||||
|
||||
private fun setupActionBar() {
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.run {
|
||||
title = null
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
|
@ -388,40 +391,40 @@ class ComposeActivity : BaseActivity(),
|
|||
val animateAvatars = preferences.getBoolean("animateGifAvatars", false)
|
||||
loadAvatar(
|
||||
activeAccount.profilePictureUrl,
|
||||
composeAvatar,
|
||||
binding.composeAvatar,
|
||||
avatarSize / 8,
|
||||
animateAvatars
|
||||
)
|
||||
composeAvatar.contentDescription = getString(R.string.compose_active_account_description,
|
||||
binding.composeAvatar.contentDescription = getString(R.string.compose_active_account_description,
|
||||
activeAccount.fullName)
|
||||
}
|
||||
|
||||
private fun replaceTextAtCaret(text: CharSequence) {
|
||||
// If you select "backward" in an editable, you get SelectionStart > SelectionEnd
|
||||
val start = composeEditField.selectionStart.coerceAtMost(composeEditField.selectionEnd)
|
||||
val end = composeEditField.selectionStart.coerceAtLeast(composeEditField.selectionEnd)
|
||||
val textToInsert = if (start > 0 && !composeEditField.text[start - 1].isWhitespace()) {
|
||||
val start = binding.composeEditField.selectionStart.coerceAtMost(binding.composeEditField.selectionEnd)
|
||||
val end = binding.composeEditField.selectionStart.coerceAtLeast(binding.composeEditField.selectionEnd)
|
||||
val textToInsert = if (start > 0 && !binding.composeEditField.text[start - 1].isWhitespace()) {
|
||||
" $text"
|
||||
} else {
|
||||
text
|
||||
}
|
||||
composeEditField.text.replace(start, end, textToInsert)
|
||||
binding.composeEditField.text.replace(start, end, textToInsert)
|
||||
|
||||
// Set the cursor after the inserted text
|
||||
composeEditField.setSelection(start + text.length)
|
||||
binding.composeEditField.setSelection(start + text.length)
|
||||
}
|
||||
|
||||
fun prependSelectedWordsWith(text: CharSequence) {
|
||||
// If you select "backward" in an editable, you get SelectionStart > SelectionEnd
|
||||
val start = composeEditField.selectionStart.coerceAtMost(composeEditField.selectionEnd)
|
||||
val end = composeEditField.selectionStart.coerceAtLeast(composeEditField.selectionEnd)
|
||||
val editorText = composeEditField.text
|
||||
val start = binding.composeEditField.selectionStart.coerceAtMost(binding.composeEditField.selectionEnd)
|
||||
val end = binding.composeEditField.selectionStart.coerceAtLeast(binding.composeEditField.selectionEnd)
|
||||
val editorText = binding.composeEditField.text
|
||||
|
||||
if (start == end) {
|
||||
// No selection, just insert text at caret
|
||||
editorText.insert(start, text)
|
||||
// Set the cursor after the inserted text
|
||||
composeEditField.setSelection(start + text.length)
|
||||
binding.composeEditField.setSelection(start + text.length)
|
||||
} else {
|
||||
var wasWord: Boolean
|
||||
var isWord = end < editorText.length && !Character.isWhitespace(editorText[end])
|
||||
|
@ -447,7 +450,7 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
// Keep the same text (including insertions) selected
|
||||
composeEditField.setSelection(start, newEnd)
|
||||
binding.composeEditField.setSelection(start, newEnd)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +469,7 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
private fun displayTransientError(@StringRes stringId: Int) {
|
||||
val bar = Snackbar.make(activityCompose, stringId, Snackbar.LENGTH_LONG)
|
||||
val bar = Snackbar.make(binding.activityCompose, stringId, Snackbar.LENGTH_LONG)
|
||||
//necessary so snackbar is shown over everything
|
||||
bar.view.elevation = resources.getDimension(R.dimen.compose_activity_snackbar_elevation)
|
||||
bar.show()
|
||||
|
@ -478,49 +481,49 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun updateSensitiveMediaToggle(markMediaSensitive: Boolean, contentWarningShown: Boolean) {
|
||||
if (viewModel.media.value.isNullOrEmpty()) {
|
||||
composeHideMediaButton.hide()
|
||||
binding.composeHideMediaButton.hide()
|
||||
} else {
|
||||
composeHideMediaButton.show()
|
||||
binding.composeHideMediaButton.show()
|
||||
@ColorInt val color = if (contentWarningShown) {
|
||||
composeHideMediaButton.setImageResource(R.drawable.ic_hide_media_24dp)
|
||||
composeHideMediaButton.isClickable = false
|
||||
binding.composeHideMediaButton.setImageResource(R.drawable.ic_hide_media_24dp)
|
||||
binding.composeHideMediaButton.isClickable = false
|
||||
ContextCompat.getColor(this, R.color.transparent_tusky_blue)
|
||||
|
||||
} else {
|
||||
composeHideMediaButton.isClickable = true
|
||||
binding.composeHideMediaButton.isClickable = true
|
||||
if (markMediaSensitive) {
|
||||
composeHideMediaButton.setImageResource(R.drawable.ic_hide_media_24dp)
|
||||
binding.composeHideMediaButton.setImageResource(R.drawable.ic_hide_media_24dp)
|
||||
ContextCompat.getColor(this, R.color.tusky_blue)
|
||||
} else {
|
||||
composeHideMediaButton.setImageResource(R.drawable.ic_eye_24dp)
|
||||
binding.composeHideMediaButton.setImageResource(R.drawable.ic_eye_24dp)
|
||||
ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
}
|
||||
}
|
||||
composeHideMediaButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
binding.composeHideMediaButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateScheduleButton() {
|
||||
@ColorInt val color = if (composeScheduleView.time == null) {
|
||||
@ColorInt val color = if (binding.composeScheduleView.time == null) {
|
||||
ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
} else {
|
||||
ContextCompat.getColor(this, R.color.tusky_blue)
|
||||
}
|
||||
composeScheduleButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
binding.composeScheduleButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun enableButtons(enable: Boolean) {
|
||||
composeAddMediaButton.isClickable = enable
|
||||
composeToggleVisibilityButton.isClickable = enable
|
||||
composeEmojiButton.isClickable = enable
|
||||
composeHideMediaButton.isClickable = enable
|
||||
composeScheduleButton.isClickable = enable
|
||||
composeTootButton.isEnabled = enable
|
||||
binding.composeAddMediaButton.isClickable = enable
|
||||
binding.composeToggleVisibilityButton.isClickable = enable
|
||||
binding.composeEmojiButton.isClickable = enable
|
||||
binding.composeHideMediaButton.isClickable = enable
|
||||
binding.composeScheduleButton.isClickable = enable
|
||||
binding.composeTootButton.isEnabled = enable
|
||||
}
|
||||
|
||||
private fun setStatusVisibility(visibility: Status.Visibility) {
|
||||
composeOptionsBottomSheet.setStatusVisibility(visibility)
|
||||
composeTootButton.setStatusVisibility(visibility)
|
||||
binding.composeOptionsBottomSheet.setStatusVisibility(visibility)
|
||||
binding.composeTootButton.setStatusVisibility(visibility)
|
||||
|
||||
val iconRes = when (visibility) {
|
||||
Status.Visibility.PUBLIC -> R.drawable.ic_public_24dp
|
||||
|
@ -529,7 +532,7 @@ class ComposeActivity : BaseActivity(),
|
|||
Status.Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp
|
||||
else -> R.drawable.ic_lock_open_24dp
|
||||
}
|
||||
composeToggleVisibilityButton.setImageResource(iconRes)
|
||||
binding.composeToggleVisibilityButton.setImageResource(iconRes)
|
||||
}
|
||||
|
||||
private fun showComposeOptions() {
|
||||
|
@ -545,7 +548,7 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun onScheduleClick() {
|
||||
if (viewModel.scheduledAt.value == null) {
|
||||
composeScheduleView.openPickDateDialog()
|
||||
binding.composeScheduleView.openPickDateDialog()
|
||||
} else {
|
||||
showScheduleView()
|
||||
}
|
||||
|
@ -563,7 +566,7 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
private fun showEmojis() {
|
||||
emojiView.adapter?.let {
|
||||
binding.emojiView.adapter?.let {
|
||||
if (it.itemCount == 0) {
|
||||
val errorMessage = getString(R.string.error_no_custom_emojis, accountManager.activeAccount!!.domain)
|
||||
Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show()
|
||||
|
@ -626,10 +629,10 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
val layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
layoutParams.setMargins(margin, margin, margin, marginBottom)
|
||||
pollPreview.layoutParams = layoutParams
|
||||
binding.pollPreview.layoutParams = layoutParams
|
||||
|
||||
pollPreview.setOnClickListener {
|
||||
val popup = PopupMenu(this, pollPreview)
|
||||
binding.pollPreview.setOnClickListener {
|
||||
val popup = PopupMenu(this, binding.pollPreview)
|
||||
val editId = 1
|
||||
val removeId = 2
|
||||
popup.menu.add(0, editId, 0, R.string.edit_poll)
|
||||
|
@ -647,7 +650,7 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun removePoll() {
|
||||
viewModel.poll.value = null
|
||||
pollPreview.hide()
|
||||
binding.pollPreview.hide()
|
||||
}
|
||||
|
||||
override fun onVisibilityChanged(visibility: Status.Visibility) {
|
||||
|
@ -658,39 +661,39 @@ class ComposeActivity : BaseActivity(),
|
|||
@VisibleForTesting
|
||||
fun calculateTextLength(): Int {
|
||||
var offset = 0
|
||||
val urlSpans = composeEditField.urls
|
||||
val urlSpans = binding.composeEditField.urls
|
||||
if (urlSpans != null) {
|
||||
for (span in urlSpans) {
|
||||
offset += max(0, span.url.length - MAXIMUM_URL_LENGTH)
|
||||
}
|
||||
}
|
||||
var length = composeEditField.length() - offset
|
||||
var length = binding.composeEditField.length() - offset
|
||||
if (viewModel.showContentWarning.value!!) {
|
||||
length += composeContentWarningField.length()
|
||||
length += binding.composeContentWarningField.length()
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
private fun updateVisibleCharactersLeft() {
|
||||
val remainingLength = maximumTootCharacters - calculateTextLength()
|
||||
composeCharactersLeftView.text = String.format(Locale.getDefault(), "%d", remainingLength)
|
||||
binding.composeCharactersLeftView.text = String.format(Locale.getDefault(), "%d", remainingLength)
|
||||
|
||||
val textColor = if (remainingLength < 0) {
|
||||
ContextCompat.getColor(this, R.color.tusky_red)
|
||||
} else {
|
||||
ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
}
|
||||
composeCharactersLeftView.setTextColor(textColor)
|
||||
binding.composeCharactersLeftView.setTextColor(textColor)
|
||||
}
|
||||
|
||||
private fun onContentWarningChanged() {
|
||||
val showWarning = composeContentWarningBar.isGone
|
||||
val showWarning = binding.composeContentWarningBar.isGone
|
||||
viewModel.contentWarningChanged(showWarning)
|
||||
updateVisibleCharactersLeft()
|
||||
}
|
||||
|
||||
private fun verifyScheduledTime(): Boolean {
|
||||
return composeScheduleView.verifyScheduledTime(composeScheduleView.getDateTime(viewModel.scheduledAt.value))
|
||||
return binding.composeScheduleView.verifyScheduledTime(binding.composeScheduleView.getDateTime(viewModel.scheduledAt.value))
|
||||
}
|
||||
|
||||
private fun onSendClicked() {
|
||||
|
@ -725,14 +728,14 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun sendStatus() {
|
||||
enableButtons(false)
|
||||
val contentText = composeEditField.text.toString()
|
||||
val contentText = binding.composeEditField.text.toString()
|
||||
var spoilerText = ""
|
||||
if (viewModel.showContentWarning.value!!) {
|
||||
spoilerText = composeContentWarningField.text.toString()
|
||||
spoilerText = binding.composeContentWarningField.text.toString()
|
||||
}
|
||||
val characterCount = calculateTextLength()
|
||||
if ((characterCount <= 0 || contentText.isBlank()) && viewModel.media.value!!.isEmpty()) {
|
||||
composeEditField.error = getString(R.string.error_empty)
|
||||
binding.composeEditField.error = getString(R.string.error_empty)
|
||||
enableButtons(true)
|
||||
} else if (characterCount <= maximumTootCharacters) {
|
||||
if (viewModel.media.value!!.isNotEmpty()) {
|
||||
|
@ -747,7 +750,7 @@ class ComposeActivity : BaseActivity(),
|
|||
})
|
||||
|
||||
} else {
|
||||
composeEditField.error = getString(R.string.error_compose_character_limit)
|
||||
binding.composeEditField.error = getString(R.string.error_compose_character_limit)
|
||||
enableButtons(true)
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +761,7 @@ class ComposeActivity : BaseActivity(),
|
|||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
initiateMediaPicking()
|
||||
} else {
|
||||
val bar = Snackbar.make(activityCompose, R.string.error_media_upload_permission,
|
||||
val bar = Snackbar.make(binding.activityCompose, R.string.error_media_upload_permission,
|
||||
Snackbar.LENGTH_SHORT).apply {
|
||||
|
||||
}
|
||||
|
@ -813,12 +816,12 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
private fun enablePollButton(enable: Boolean) {
|
||||
addPollTextActionTextView.isEnabled = enable
|
||||
binding.addPollTextActionTextView.isEnabled = enable
|
||||
val textColor = ThemeUtils.getColor(this,
|
||||
if (enable) android.R.attr.textColorTertiary
|
||||
else R.attr.textColorDisabled)
|
||||
addPollTextActionTextView.setTextColor(textColor)
|
||||
addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN)
|
||||
binding.addPollTextActionTextView.setTextColor(textColor)
|
||||
binding.addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
private fun removeMediaFromQueue(item: QueuedMedia) {
|
||||
|
@ -879,19 +882,18 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
private fun showContentWarning(show: Boolean) {
|
||||
TransitionManager.beginDelayedTransition(composeContentWarningBar.parent as ViewGroup)
|
||||
TransitionManager.beginDelayedTransition(binding.composeContentWarningBar.parent as ViewGroup)
|
||||
@ColorInt val color = if (show) {
|
||||
composeContentWarningBar.show()
|
||||
composeContentWarningField.setSelection(composeContentWarningField.text.length)
|
||||
composeContentWarningField.requestFocus()
|
||||
binding.composeContentWarningBar.show()
|
||||
binding.composeContentWarningField.setSelection(binding.composeContentWarningField.text.length)
|
||||
binding.composeContentWarningField.requestFocus()
|
||||
ContextCompat.getColor(this, R.color.tusky_blue)
|
||||
} else {
|
||||
composeContentWarningBar.hide()
|
||||
composeEditField.requestFocus()
|
||||
binding.composeContentWarningBar.hide()
|
||||
binding.composeEditField.requestFocus()
|
||||
ThemeUtils.getColor(this, android.R.attr.textColorTertiary)
|
||||
}
|
||||
composeContentWarningButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
binding.composeContentWarningButton.drawable.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
@ -939,8 +941,8 @@ class ComposeActivity : BaseActivity(),
|
|||
}
|
||||
|
||||
private fun handleCloseButton() {
|
||||
val contentText = composeEditField.text.toString()
|
||||
val contentWarning = composeContentWarningField.text.toString()
|
||||
val contentText = binding.composeEditField.text.toString()
|
||||
val contentWarning = binding.composeContentWarningField.text.toString()
|
||||
if (viewModel.didChange(contentText, contentWarning)) {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(R.string.compose_save_draft)
|
||||
|
@ -974,8 +976,8 @@ class ComposeActivity : BaseActivity(),
|
|||
|
||||
private fun setEmojiList(emojiList: List<Emoji>?) {
|
||||
if (emojiList != null) {
|
||||
emojiView.adapter = EmojiAdapter(emojiList, this@ComposeActivity)
|
||||
enableButton(composeEmojiButton, true, emojiList.isNotEmpty())
|
||||
binding.emojiView.adapter = EmojiAdapter(emojiList, this@ComposeActivity)
|
||||
enableButton(binding.composeEmojiButton, true, emojiList.isNotEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ import android.os.Bundle
|
|||
import com.keylesspalace.tusky.BaseActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.components.instancemute.fragment.InstanceListFragment
|
||||
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import javax.inject.Inject
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
|
||||
class InstanceListActivity: BaseActivity(), HasAndroidInjector {
|
||||
|
||||
|
@ -16,9 +16,10 @@ class InstanceListActivity: BaseActivity(), HasAndroidInjector {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val binding = ActivityAccountListBinding.inflate(layoutInflater)
|
||||
setContentView(R.layout.activity_account_list)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.apply {
|
||||
setTitle(R.string.title_domain_mutes)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
|
|
|
@ -28,12 +28,12 @@ import com.keylesspalace.tusky.MainActivity
|
|||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
|
||||
import com.keylesspalace.tusky.databinding.ActivityPreferencesBinding
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.getNonNullString
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
|
@ -48,12 +48,12 @@ class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreference
|
|||
private var restartActivitiesOnExit: Boolean = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_preferences)
|
||||
val binding = ActivityPreferencesBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
|
|
|
@ -22,11 +22,11 @@ import androidx.activity.viewModels
|
|||
import com.keylesspalace.tusky.BottomSheetActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.components.report.adapter.ReportPagerAdapter
|
||||
import com.keylesspalace.tusky.databinding.ActivityReportBinding
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.activity_report.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||
|
@ -39,6 +39,8 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
|
||||
private val viewModel: ReportViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivityReportBinding::inflate)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val accountId = intent?.getStringExtra(ACCOUNT_ID)
|
||||
|
@ -50,9 +52,9 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
viewModel.init(accountId, accountUserName, intent?.getStringExtra(STATUS_ID))
|
||||
|
||||
|
||||
setContentView(R.layout.activity_report)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
|
||||
supportActionBar?.apply {
|
||||
title = getString(R.string.report_username_format, viewModel.accountUserName)
|
||||
|
@ -69,8 +71,8 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
}
|
||||
|
||||
private fun initViewPager() {
|
||||
wizard.isUserInputEnabled = false
|
||||
wizard.adapter = ReportPagerAdapter(this)
|
||||
binding.wizard.isUserInputEnabled = false
|
||||
binding.wizard.adapter = ReportPagerAdapter(this)
|
||||
}
|
||||
|
||||
private fun subscribeObservables() {
|
||||
|
@ -96,18 +98,18 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
}
|
||||
|
||||
private fun showPreviousScreen() {
|
||||
when (wizard.currentItem) {
|
||||
when (binding.wizard.currentItem) {
|
||||
0 -> closeScreen()
|
||||
1 -> showStatusesPage()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDonePage() {
|
||||
wizard.currentItem = 2
|
||||
binding.wizard.currentItem = 2
|
||||
}
|
||||
|
||||
private fun showNotesPage() {
|
||||
wizard.currentItem = 1
|
||||
binding.wizard.currentItem = 1
|
||||
}
|
||||
|
||||
private fun closeScreen() {
|
||||
|
@ -115,7 +117,7 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
}
|
||||
|
||||
private fun showStatusesPage() {
|
||||
wizard.currentItem = 0
|
||||
binding.wizard.currentItem = 0
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -18,20 +18,19 @@ package com.keylesspalace.tusky.components.scheduled
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.activity.viewModels
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.keylesspalace.tusky.BaseActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||
import com.keylesspalace.tusky.databinding.ActivityScheduledTootBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.ScheduledStatus
|
||||
import com.keylesspalace.tusky.util.Status
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.show
|
||||
import kotlinx.android.synthetic.main.activity_scheduled_toot.*
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injectable {
|
||||
|
@ -39,31 +38,31 @@ class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injec
|
|||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelFactory
|
||||
|
||||
lateinit var viewModel: ScheduledTootViewModel
|
||||
private val viewModel: ScheduledTootViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val adapter = ScheduledTootAdapter(this)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_scheduled_toot)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
val binding = ActivityScheduledTootBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
title = getString(R.string.title_scheduled_toot)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this::refreshStatuses)
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this::refreshStatuses)
|
||||
binding.swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)
|
||||
|
||||
scheduledTootList.setHasFixedSize(true)
|
||||
scheduledTootList.layoutManager = LinearLayoutManager(this)
|
||||
binding.scheduledTootList.setHasFixedSize(true)
|
||||
binding.scheduledTootList.layoutManager = LinearLayoutManager(this)
|
||||
val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
|
||||
scheduledTootList.addItemDecoration(divider)
|
||||
scheduledTootList.adapter = adapter
|
||||
|
||||
viewModel = ViewModelProvider(this, viewModelFactory)[ScheduledTootViewModel::class.java]
|
||||
binding.scheduledTootList.addItemDecoration(divider)
|
||||
binding.scheduledTootList.adapter = adapter
|
||||
|
||||
viewModel.data.observe(this) {
|
||||
adapter.submitList(it)
|
||||
|
@ -72,31 +71,31 @@ class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injec
|
|||
viewModel.networkState.observe(this) { (status) ->
|
||||
when(status) {
|
||||
Status.SUCCESS -> {
|
||||
progressBar.hide()
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
binding.progressBar.hide()
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
if(viewModel.data.value?.loadedCount == 0) {
|
||||
errorMessageView.setup(R.drawable.elephant_friend_empty, R.string.no_scheduled_status)
|
||||
errorMessageView.show()
|
||||
binding.errorMessageView.setup(R.drawable.elephant_friend_empty, R.string.no_scheduled_status)
|
||||
binding.errorMessageView.show()
|
||||
} else {
|
||||
errorMessageView.hide()
|
||||
binding.errorMessageView.hide()
|
||||
}
|
||||
}
|
||||
Status.RUNNING -> {
|
||||
errorMessageView.hide()
|
||||
binding.errorMessageView.hide()
|
||||
if(viewModel.data.value?.loadedCount ?: 0 > 0) {
|
||||
swipeRefreshLayout.isRefreshing = true
|
||||
binding.swipeRefreshLayout.isRefreshing = true
|
||||
} else {
|
||||
progressBar.show()
|
||||
binding.progressBar.show()
|
||||
}
|
||||
}
|
||||
Status.FAILED -> {
|
||||
if(viewModel.data.value?.loadedCount ?: 0 >= 0) {
|
||||
progressBar.hide()
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
errorMessageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
binding.progressBar.hide()
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
binding.errorMessageView.setup(R.drawable.elephant_error, R.string.error_generic) {
|
||||
refreshStatuses()
|
||||
}
|
||||
errorMessageView.show()
|
||||
binding.errorMessageView.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,10 +26,11 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||
import com.keylesspalace.tusky.BottomSheetActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.components.search.adapter.SearchPagerAdapter
|
||||
import com.keylesspalace.tusky.databinding.ActivitySearchBinding
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.activity_search.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SearchActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||
|
@ -41,10 +42,12 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
|
||||
private val viewModel: SearchViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val binding by viewBinding(ActivitySearchBinding::inflate)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_search)
|
||||
setSupportActionBar(toolbar)
|
||||
setContentView(binding.root)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.apply {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
|
@ -55,9 +58,9 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||
}
|
||||
|
||||
private fun setupPages() {
|
||||
pages.adapter = SearchPagerAdapter(this)
|
||||
binding.pages.adapter = SearchPagerAdapter(this)
|
||||
|
||||
TabLayoutMediator(tabs, pages) {
|
||||
TabLayoutMediator(binding.tabs, binding.pages) {
|
||||
tab, position ->
|
||||
tab.text = getPageTitle(position)
|
||||
}.attach()
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.keylesspalace.tusky.util
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.viewbinding.ViewBinding
|
||||
|
||||
/**
|
||||
* https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c
|
||||
*/
|
||||
|
||||
inline fun <T : ViewBinding> AppCompatActivity.viewBinding(
|
||||
crossinline bindingInflater: (LayoutInflater) -> T
|
||||
) = lazy(LazyThreadSafetyMode.NONE) {
|
||||
bindingInflater(layoutInflater)
|
||||
}
|
|
@ -6,7 +6,9 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.AboutActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -248,20 +248,63 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/accountFieldList"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ViewStub
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/accountMovedView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inflatedId="@+id/accountMovedViewLayout"
|
||||
android:layout="@layout/view_account_moved"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountRemoveView" />
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="accountMovedText,accountMovedAvatar,accountMovedDisplayName,accountMovedUsername" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrierRemote"
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/accountMovedText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="accountMovedView,accountMovedViewLayout" />
|
||||
android:layout_marginTop="12dp"
|
||||
android:drawablePadding="6dp"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountRemoveView"
|
||||
tools:text="Account has moved" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/accountMovedAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedText"
|
||||
tools:src="@drawable/avatar_default" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/accountMovedDisplayName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="?attr/status_text_large"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/accountMovedUsername"
|
||||
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintTop_toTopOf="@id/accountMovedAvatar"
|
||||
tools:text="Display name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountMovedUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintBottom_toBottomOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedDisplayName"
|
||||
tools:text="\@username" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/accountStatuses"
|
||||
|
@ -272,7 +315,7 @@
|
|||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toStartOf="@id/accountFollowing"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrierRemote">
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedAvatar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountStatusesTextView"
|
||||
|
@ -303,7 +346,7 @@
|
|||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toStartOf="@id/accountFollowers"
|
||||
app:layout_constraintStart_toEndOf="@id/accountStatuses"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrierRemote">
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedAvatar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountFollowingTextView"
|
||||
|
@ -333,7 +376,7 @@
|
|||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/accountFollowing"
|
||||
app:layout_constraintTop_toBottomOf="@id/barrierRemote">
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedAvatar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountFollowersTextView"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.AccountListActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.EditProfileActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/scrollView"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/activityFilters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.FiltersActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/filtersView"
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.AboutActivity">
|
||||
tools:context=".LicenseActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/listsRecycler"
|
||||
|
@ -18,7 +20,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/appbar" />
|
||||
app:layout_constraintTop_toBottomOf="@id/includedToolbar" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
@ -39,7 +41,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/appbar"
|
||||
app:layout_constraintTop_toBottomOf="@id/includedToolbar"
|
||||
tools:visibility="visible"
|
||||
app:layout_constrainedHeight="true" />
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.ModalTimelineActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/contentFrame"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.components.preference.PreferencesActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".components.report.ReportActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/wizard"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/activityScheduledToot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.AccountListActivity">
|
||||
tools:context=".components.scheduled.ScheduledTootActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.StatusListActivity">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/tabPreferenceContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/toolbar_basic" />
|
||||
<include
|
||||
android:id="@+id/includedToolbar"
|
||||
layout="@layout/toolbar_basic" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/currentTabsRecyclerView"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/activity_view_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.keylesspalace.tusky.ViewTagActivity">
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/accountMovedText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="6dp"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Account has moved" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/accountMovedAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedText"
|
||||
tools:src="@drawable/avatar_default" />
|
||||
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/accountMovedDisplayName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="?attr/status_text_large"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/accountMovedUsername"
|
||||
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintTop_toTopOf="@id/accountMovedAvatar"
|
||||
tools:text="Display name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountMovedUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintBottom_toBottomOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintStart_toEndOf="@id/accountMovedAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountMovedDisplayName"
|
||||
tools:text="\@username" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in a new issue