Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/java/one/mixin/android/MixinApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import leakcanary.AppWatcher
import leakcanary.LeakCanaryProcess
import leakcanary.ReachabilityWatcher
import okhttp3.OkHttpClient
import one.mixin.android.Constants.Account.PREF_APP_AUTH
import one.mixin.android.crypto.CryptoWalletHelper
import one.mixin.android.crypto.MixinSignalProtocolLogger
import one.mixin.android.crypto.PrivacyPreference.clearPrivacyPreferences
Expand All @@ -61,6 +62,7 @@ import one.mixin.android.extension.isNightMode
import one.mixin.android.extension.notificationManager
import one.mixin.android.extension.putBoolean
import one.mixin.android.extension.putLong
import one.mixin.android.extension.remove
import one.mixin.android.job.BlazeMessageService
import one.mixin.android.job.MixinJobManager
import one.mixin.android.session.Session
Expand Down Expand Up @@ -319,6 +321,7 @@ open class MixinApplication :
releaseAll()
PipVideoView.release()
removeValueFromEncryptedPreferences(this@MixinApplication, Constants.Tip.MNEMONIC)
defaultSharedPreferences.remove(PREF_APP_AUTH)
applicationScope.launch {
clearData(sessionId)
withContext(Dispatchers.Main) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ fun showAppAuthPrompt(
val biometricPromptInfo =
BiometricPrompt.PromptInfo.Builder()
.setTitle(title)
.setSubtitle("")
.setNegativeButtonText(negativeBtnText)
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@ package one.mixin.android.ui.common

import android.content.Context
import android.view.View
import one.mixin.android.extension.getSafeAreaInsetsBottom
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import one.mixin.android.extension.getSafeAreaInsetsTop
import one.mixin.android.extension.screenHeight

internal fun Context.resolveBottomSheetPeekHeight(
view: View,
contentHeight: Int,
includeBottomInset: Boolean = true,
): Int {
if (contentHeight <= 0) return 0
if (!includeBottomInset) return contentHeight

val screenHeight = screenHeight()
val fullHeight = screenHeight - view.getSafeAreaInsetsTop()
val bottomInset = if (contentHeight < fullHeight) view.getSafeAreaInsetsBottom() else 0
val topInset = view.getSafeAreaInsetsTop()
val fullHeight = screenHeight - topInset
val sheetView = view.parent as? View
val appliedBottomInset = sheetView?.paddingBottom ?: 0
val availableHeight = (sheetView?.parent as? View)?.height ?: fullHeight
val consumedBottomInset = (fullHeight - availableHeight).coerceAtLeast(0)
Comment thread
SeniorZhai marked this conversation as resolved.
val tappableBottomInset =
ViewCompat.getRootWindowInsets(view)
?.getInsets(WindowInsetsCompat.Type.tappableElement())
?.bottom
?: 0
val remainingTappableBottomInset = (tappableBottomInset - consumedBottomInset).coerceAtLeast(0)
val bottomInset =
if (contentHeight < fullHeight) {
maxOf(appliedBottomInset, remainingTappableBottomInset)
} else {
0
}

return (contentHeight + bottomInset).coerceAtMost(screenHeight)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import android.content.ClipData
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.View.MeasureSpec
import android.view.ViewGroup
import androidx.core.view.doOnPreDraw
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
Expand All @@ -31,13 +30,12 @@ import one.mixin.android.databinding.FragmentGroupBottomSheetBinding
import one.mixin.android.extension.addFragment
import one.mixin.android.extension.alertDialogBuilder
import one.mixin.android.extension.dayTime
import one.mixin.android.extension.dp
import one.mixin.android.extension.getClipboardManager
import one.mixin.android.extension.localTime
import one.mixin.android.extension.navigationBarHeight
import one.mixin.android.extension.notNullWithElse
import one.mixin.android.extension.showConfirmDialog
import one.mixin.android.extension.toast
import one.mixin.android.extension.dp
import one.mixin.android.session.Session
import one.mixin.android.ui.common.info.MenuStyle
import one.mixin.android.ui.common.info.MixinScrollableBottomSheetDialogFragment
Expand Down Expand Up @@ -110,6 +108,17 @@ class GroupBottomSheetDialogFragment : MixinScrollableBottomSheetDialogFragment(
FragmentGroupBottomSheetBinding.bind(contentView)
}

override fun getPeekHeight(
contentView: View,
behavior: BottomSheetBehavior<*>,
): Int = calculateCollapsedContentHeight()

override fun shouldApplyBottomInsetToBottomSheetContainer(): Boolean = false

override fun shouldIncludeBottomInsetInPeekHeight(): Boolean = false

override fun extraPeekOffsetWhenNavigationBarPresent(): Int = 5.dp

override fun setupDialog(
dialog: Dialog,
style: Int,
Expand Down Expand Up @@ -144,31 +153,7 @@ class GroupBottomSheetDialogFragment : MixinScrollableBottomSheetDialogFragment(
if (icon == null || !File(icon).exists()) {
bottomViewModel.startGenerateAvatar(c.conversationId)
}
binding.name.text = c.name
if (c.announcement.isNullOrBlank()) {
binding.detailTv.isVisible = false
} else {
binding.detailTv.isVisible = true
binding.detailTv.originalText = c.announcement
binding.detailTv.heightDifferenceCallback = { heightDifference, duration ->
if (behavior?.state == BottomSheetBehavior.STATE_COLLAPSED) {
behavior?.peekHeight?.let { peekHeight ->
ValueAnimator.ofInt(peekHeight, peekHeight + heightDifference).apply {
interpolator = FastOutSlowInInterpolator()
setDuration(duration)
addUpdateListener { value ->
behavior?.peekHeight = value.animatedValue as Int
}
start()
}
}
} else if (behavior?.state == BottomSheetBehavior.STATE_EXPANDED) {
behavior?.peekHeight?.let { peekHeight ->
behavior?.peekHeight = heightDifference + peekHeight
}
}
}
}
renderCollapsedContent(c)
initParticipant(changeMenu, c)
},
)
Expand Down Expand Up @@ -222,13 +207,7 @@ class GroupBottomSheetDialogFragment : MixinScrollableBottomSheetDialogFragment(
binding.memberTv.isVisible = true
}

contentView.doOnPreDraw {
binding.opsLl.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = requireContext().navigationBarHeight() + 24.dp
}
behavior?.peekHeight = binding.title.height + binding.scrollContent.height -
(menuListLayout?.height ?: 0) - if (menuListLayout != null) 38.dp else 8.dp
}
updateCollapsedPeekHeight()
}

private fun initMenu(
Expand Down Expand Up @@ -395,16 +374,15 @@ class GroupBottomSheetDialogFragment : MixinScrollableBottomSheetDialogFragment(
},
)

menuListLayout?.removeAllViews()
binding.scrollContent.removeView(menuListLayout)
binding.menuContainer.removeAllViews()
list.createMenuLayout(
requireContext(),
getString(R.string.Created, conversation.createdAt.dayTime()),
)
.let { layout ->
menuListLayout = layout
binding.scrollContent.addView(layout)
binding.scrollContent.setPadding(0, 0, 0, 0)
binding.menuContainer.addView(layout)
updateCollapsedPeekHeight()
binding.moreFl.setOnClickListener {
if (behavior?.state == BottomSheetBehavior.STATE_COLLAPSED) {
behavior?.state = BottomSheetBehavior.STATE_EXPANDED
Expand All @@ -418,6 +396,57 @@ class GroupBottomSheetDialogFragment : MixinScrollableBottomSheetDialogFragment(
}
}

private fun renderCollapsedContent(conversation: Conversation) {
if (!isAdded) return

binding.name.text = conversation.name
if (conversation.announcement.isNullOrBlank()) {
binding.detailTv.isVisible = false
} else {
binding.detailTv.isVisible = true
binding.detailTv.originalText = conversation.announcement
binding.detailTv.heightDifferenceCallback = { heightDifference, duration ->
if (behavior?.state == BottomSheetBehavior.STATE_COLLAPSED) {
behavior?.peekHeight?.let { peekHeight ->
ValueAnimator.ofInt(peekHeight, peekHeight + heightDifference).apply {
interpolator = FastOutSlowInInterpolator()
setDuration(duration)
addUpdateListener { value ->
behavior?.peekHeight = value.animatedValue as Int
}
start()
}
}
} else if (behavior?.state == BottomSheetBehavior.STATE_EXPANDED) {
behavior?.peekHeight?.let { peekHeight ->
behavior?.peekHeight = heightDifference + peekHeight
}
}
}
}
updateCollapsedPeekHeight()
}

private fun updateCollapsedPeekHeight() {
schedulePeekHeightUpdate()
}

private fun calculateCollapsedContentHeight(): Int {
val titleHeight = binding.title.height.takeIf { it > 0 } ?: measureCollapsedViewHeight(binding.title)
val topContentHeight = binding.topContent.height.takeIf { it > 0 } ?: measureCollapsedViewHeight(binding.topContent)
return titleHeight + topContentHeight
}

private fun measureCollapsedViewHeight(view: View): Int {
val width = contentView.measuredWidth.takeIf { it > 0 } ?: contentView.width
if (width <= 0) return 0

val widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY)
val heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
view.measure(widthSpec, heightSpec)
return view.measuredHeight
}

private fun startSearchConversation() =
lifecycleScope.launch {
bottomViewModel.getConversation(conversationId)?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class LoginVerifyBottomSheetDialogFragment : BiometricBottomSheetDialogFragment(
val bottomSheet = builder.create()
menuBinding.closeIv.setOnClickListener { bottomSheet.dismiss() }
menuBinding.forgetPinTv.setOnClickListener {
context?.openUrl(getString(R.string.What_is_Pin_url))
context?.openUrl(getString(R.string.forget_pin_help_url))
bottomSheet.dismiss()
}
menuBinding.switchAccountTv.setOnClickListener {
Expand Down
Loading
Loading