From f8475f8615225ba6d91099c039752dea19af83ea Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 4 Oct 2020 03:25:12 +0300 Subject: [PATCH] chats: implement creating new chat through account activity --- app/src/husky/res/values/strings.xml | 9 +- .../keylesspalace/tusky/AccountActivity.kt | 90 ++++++++++++++++++- .../com/keylesspalace/tusky/entity/Account.kt | 1 + .../tusky/fragment/TimelineFragment.java | 1 + .../interfaces/ActionButtonActivity.java | 2 + app/src/main/res/layout/activity_account.xml | 28 +++++- 6 files changed, 124 insertions(+), 7 deletions(-) diff --git a/app/src/husky/res/values/strings.xml b/app/src/husky/res/values/strings.xml index 2e92d404..2ef938cc 100644 --- a/app/src/husky/res/values/strings.xml +++ b/app/src/husky/res/values/strings.xml @@ -1,9 +1,11 @@ Chats - You: %s - Mark as read + You + + Recipient does not support Chats + Mark as read Reply to React Remove reaction @@ -12,7 +14,8 @@ Disable %s Stickers Open in external app - Open a chat + Open chat + Expand menu %s reacted by diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt index de303973..4610420f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt @@ -15,6 +15,8 @@ package com.keylesspalace.tusky +import android.animation.Animator +import android.animation.AnimatorListenerAdapter import android.animation.ArgbEvaluator import android.content.Context import android.content.Intent @@ -27,6 +29,7 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.activity.viewModels import androidx.annotation.ColorInt import androidx.annotation.Px @@ -34,6 +37,7 @@ import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityOptionsCompat import androidx.core.content.ContextCompat import androidx.emoji.text.EmojiCompat +import androidx.lifecycle.Lifecycle import androidx.lifecycle.Observer import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager @@ -48,6 +52,7 @@ import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import com.keylesspalace.tusky.adapter.AccountFieldAdapter +import com.keylesspalace.tusky.components.chat.ChatActivity import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.report.ReportActivity import com.keylesspalace.tusky.di.ViewModelFactory @@ -61,8 +66,11 @@ import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.pager.AccountPagerAdapter import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.viewmodel.AccountViewModel +import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from +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_account.* import kotlinx.android.synthetic.main.view_account_moved.* import java.text.NumberFormat @@ -160,7 +168,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI accountMuteButton.hide() accountFollowsYouTextView.hide() - // setup the RecyclerView for the account fields accountFieldList.isNestedScrollingEnabled = false accountFieldList.layoutManager = LinearLayoutManager(this) @@ -279,6 +286,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI accountFloatingActionButton.show() } if (verticalOffset < oldOffset) { + hideFabMenu() accountFloatingActionButton.hide() } } @@ -494,6 +502,57 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI } } + private fun FloatingActionButton.menuAnimate(show: Boolean) { + val height = this.height.toFloat() + + if(show) { + visibility = View.VISIBLE + alpha = 0.0f + translationY = height + + animate().setDuration(200) + .translationY(0.0f) + .alpha(1.0f) + .setListener(object : AnimatorListenerAdapter() {}) // seems listener is saved, so reset it here + .start() + } else { + animate().setDuration(200) + .translationY(height) + .alpha(0.0f) + .setListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + visibility = View.GONE + super.onAnimationEnd(animation) + } + }) + .start() + } + } + + private fun hideFabMenu() { + openedFabMenu = false + + accountFloatingActionButton.animate().setDuration(200) + .rotation(0.0f).start() + accountFloatingActionButtonChat.menuAnimate(openedFabMenu) + accountFloatingActionButtonMention.menuAnimate(openedFabMenu) + + } + + var openedFabMenu = false + private fun animateFabMenu() { + if(openedFabMenu) { + hideFabMenu() + } else { + openedFabMenu = true + + accountFloatingActionButton.animate().setDuration(200) + .rotation(135.0f).start() + accountFloatingActionButtonChat.menuAnimate(openedFabMenu) + accountFloatingActionButtonMention.menuAnimate(openedFabMenu) + } + } + /** * Update account stat info */ @@ -504,7 +563,28 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI accountFollowingTextView.text = numberFormat.format(account.followingCount) accountStatusesTextView.text = numberFormat.format(account.statusesCount) - accountFloatingActionButton.setOnClickListener { mention() } + accountFloatingActionButtonMention.setOnClickListener { mention() } + + if(account.pleroma?.acceptsChatMessages == true) { + accountFloatingActionButtonChat.setOnClickListener { + mastodonApi.createChat(account.id) + .observeOn(AndroidSchedulers.mainThread()) + .autoDispose(from(this, Lifecycle.Event.ON_DESTROY)) + .subscribe({ + val intent = ChatActivity.getIntent(this@AccountActivity, it) + startActivityWithSlideInAnimation(intent) + }, { + Toast.makeText(this@AccountActivity, getString(R.string.error_generic), Toast.LENGTH_SHORT).show() + }) + } + } else { + accountFloatingActionButtonChat.backgroundTintList = ColorStateList.valueOf(Color.GRAY) + accountFloatingActionButtonChat.setOnClickListener { + Toast.makeText(this@AccountActivity, getString(R.string.error_chat_recipient_unavailable), Toast.LENGTH_SHORT).show() + } + } + + accountFloatingActionButton.setOnClickListener { animateFabMenu() } accountFollowButton.setOnClickListener { if (viewModel.isSelf) { @@ -611,6 +691,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI updateFollowButton() if (blocking || viewModel.isSelf) { + hideFabMenu() accountFloatingActionButton.hide() accountMuteButton.hide() accountSubscribeButton.hide() @@ -624,6 +705,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI } } else { + hideFabMenu() accountFloatingActionButton.hide() accountFollowButton.hide() accountMuteButton.hide() @@ -827,6 +909,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI } else null } + override fun onActionButtonHidden() { + hideFabMenu() + } + override fun androidInjector() = dispatchingAndroidInjector companion object { diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt index 8f53504f..307f82a4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt @@ -98,6 +98,7 @@ data class StringField ( ) data class PleromaAccount( + @SerializedName("accepts_chat_messages") val acceptsChatMessages: Boolean? = null, @SerializedName("is_moderator") val isModerator: Boolean? = null, @SerializedName("is_admin") val isAdmin: Boolean? = null ) diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index aa73858f..7aeb2325 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -474,6 +474,7 @@ public class TimelineFragment extends SFragment implements if (hideFab) { if (dy > 0 && composeButton.isShown()) { composeButton.hide(); // hides the button if we're scrolling down + activity.onActionButtonHidden(); } else if (dy < 0 && !composeButton.isShown()) { composeButton.show(); // shows it if we are scrolling up } diff --git a/app/src/main/java/com/keylesspalace/tusky/interfaces/ActionButtonActivity.java b/app/src/main/java/com/keylesspalace/tusky/interfaces/ActionButtonActivity.java index 089331a1..023ddde8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/interfaces/ActionButtonActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/interfaces/ActionButtonActivity.java @@ -23,4 +23,6 @@ public interface ActionButtonActivity { /* return the ActionButton of the Activity to hide or show it on scroll */ @Nullable FloatingActionButton getActionButton(); + + default void onActionButtonHidden() {} } diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index b92ec392..285f7f93 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -391,14 +391,38 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + + + +