kopia lustrzana https://github.com/ryukoposting/Signal-Android
Update first time navigation screen.
rodzic
d003dc435a
commit
3600a4818c
|
@ -516,6 +516,14 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
|||
}
|
||||
)
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from("Clear first time navigation state"),
|
||||
isEnabled = true,
|
||||
onClick = {
|
||||
SignalStore.storyValues().userHasSeenFirstNavView = false
|
||||
}
|
||||
)
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__internal_stories_dialog_launcher),
|
||||
onClick = {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package org.thoughtcrime.securesms.stories
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
|
@ -10,14 +11,13 @@ import android.util.AttributeSet
|
|||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHash
|
||||
import org.thoughtcrime.securesms.components.CornerMask
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
|
@ -28,20 +28,22 @@ class StoryFirstTimeNavigationView @JvmOverloads constructor(
|
|||
|
||||
companion object {
|
||||
private const val BLUR_ALPHA = 0x3D
|
||||
private const val NO_BLUR_ALPHA = 0xB3
|
||||
private const val NO_BLUR_ALPHA = 0xCC
|
||||
}
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.story_first_time_navigation_view, this)
|
||||
}
|
||||
|
||||
private val tapToAdvance: LottieAnimationView = findViewById(R.id.edu_tap_icon)
|
||||
private val swipeUp: LottieAnimationView = findViewById(R.id.edu_swipe_up_icon)
|
||||
private val swipeRight: LottieAnimationView = findViewById(R.id.edu_swipe_right_icon)
|
||||
private val blurHashView: ImageView = findViewById(R.id.edu_blur_hash)
|
||||
private val overlayView: ImageView = findViewById(R.id.edu_overlay)
|
||||
private val gotIt: View = findViewById(R.id.edu_got_it)
|
||||
private val close: View = findViewById(R.id.edu_close)
|
||||
|
||||
private val cornerMask = CornerMask(this).apply {
|
||||
setRadius(DimensionUnit.DP.toPixels(18f).toInt())
|
||||
}
|
||||
private var isPlayingAnimations = false
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
|
@ -59,12 +61,14 @@ class StoryFirstTimeNavigationView @JvmOverloads constructor(
|
|||
hide()
|
||||
}
|
||||
|
||||
setOnClickListener { }
|
||||
}
|
||||
close.setOnClickListener {
|
||||
callback?.onCloseClicked()
|
||||
GlideApp.with(this).clear(blurHashView)
|
||||
blurHashView.setImageDrawable(null)
|
||||
hide()
|
||||
}
|
||||
|
||||
override fun dispatchDraw(canvas: Canvas) {
|
||||
super.dispatchDraw(canvas)
|
||||
cornerMask.mask(canvas)
|
||||
setOnClickListener { }
|
||||
}
|
||||
|
||||
fun setBlurHash(blurHash: BlurHash?) {
|
||||
|
@ -105,10 +109,47 @@ class StoryFirstTimeNavigationView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
visible = true
|
||||
startLottieAnimations()
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
visible = false
|
||||
endLottieAnimations()
|
||||
}
|
||||
|
||||
private fun startLottieAnimations() {
|
||||
isPlayingAnimations = true
|
||||
tapToAdvance.addAnimatorListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
if (isPlayingAnimations) {
|
||||
swipeUp.playAnimation()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
swipeUp.addAnimatorListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
if (isPlayingAnimations) {
|
||||
swipeRight.playAnimation()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
swipeRight.addAnimatorListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
postDelayed({
|
||||
if (isPlayingAnimations) {
|
||||
startLottieAnimations()
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
})
|
||||
|
||||
tapToAdvance.playAnimation()
|
||||
}
|
||||
|
||||
private fun endLottieAnimations() {
|
||||
isPlayingAnimations = false
|
||||
}
|
||||
|
||||
private fun isRenderEffectSupported(): Boolean {
|
||||
|
@ -118,5 +159,6 @@ class StoryFirstTimeNavigationView @JvmOverloads constructor(
|
|||
interface Callback {
|
||||
fun userHasSeenFirstNavigationView(): Boolean
|
||||
fun onGotItClicked()
|
||||
fun onCloseClicked()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.media.AudioManager
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.media.AudioManagerCompat
|
||||
|
@ -16,7 +17,9 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner
|
||||
import org.thoughtcrime.securesms.stories.StoryViewerArgs
|
||||
import org.thoughtcrime.securesms.util.FullscreenHelper
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
@ -34,9 +37,18 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
|
|||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||
StoryMutePolicy.initialize()
|
||||
Glide.get(this).setMemoryCategory(MemoryCategory.HIGH)
|
||||
FullscreenHelper.showSystemUI(window)
|
||||
|
||||
supportPostponeEnterTransition()
|
||||
|
||||
val root = findViewById<View>(android.R.id.content)
|
||||
root.setPadding(
|
||||
0,
|
||||
ViewUtil.getStatusBarHeight(root),
|
||||
0,
|
||||
ViewUtil.getNavigationBarHeight(root)
|
||||
)
|
||||
|
||||
super.onCreate(savedInstanceState, ready)
|
||||
setContentView(R.layout.fragment_container)
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package org.thoughtcrime.securesms.stories.viewer
|
||||
|
||||
import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.app.ActivityCompat
|
||||
|
@ -8,9 +11,11 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.viewpager2.widget.ViewPager2
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.stories.StoryViewerArgs
|
||||
import org.thoughtcrime.securesms.stories.viewer.first.StoryFirstTimeNavigationFragment
|
||||
import org.thoughtcrime.securesms.stories.viewer.page.StoryViewerPageArgs
|
||||
import org.thoughtcrime.securesms.stories.viewer.page.StoryViewerPageFragment
|
||||
import org.thoughtcrime.securesms.stories.viewer.reply.StoriesSharedElementCrossFaderView
|
||||
|
@ -116,6 +121,20 @@ class StoryViewerFragment :
|
|||
viewModel.addHiddenAndRefresh(ids.toSet())
|
||||
} else {
|
||||
viewModel.refresh()
|
||||
|
||||
if (!SignalStore.storyValues().userHasSeenFirstNavView) {
|
||||
StoryFirstTimeNavigationFragment().show(childFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
lifecycleDisposable += viewModel.isFirstTimeNavigationShowing.subscribe {
|
||||
if (it) {
|
||||
requireView().rootView.setRenderEffect(RenderEffect.createBlurEffect(100f, 100f, Shader.TileMode.CLAMP))
|
||||
} else {
|
||||
requireView().rootView.setRenderEffect(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,13 +53,20 @@ class StoryViewerViewModel(
|
|||
var hasConsumedInitialState = false
|
||||
private set
|
||||
|
||||
private val firstTimeNavigationPublisher: BehaviorSubject<Boolean> = BehaviorSubject.createDefault(false)
|
||||
|
||||
val isChildScrolling: Observable<Boolean> = childScrollStatePublisher.distinctUntilChanged()
|
||||
val isFirstTimeNavigationShowing: Observable<Boolean> = firstTimeNavigationPublisher.distinctUntilChanged()
|
||||
|
||||
fun addHiddenAndRefresh(hidden: Set<RecipientId>) {
|
||||
this.hidden.addAll(hidden)
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun setIsDisplayingFirstTimeNavigation(isDisplayingFirstTimeNavigation: Boolean) {
|
||||
firstTimeNavigationPublisher.onNext(isDisplayingFirstTimeNavigation)
|
||||
}
|
||||
|
||||
fun getHidden(): Set<RecipientId> = hidden
|
||||
|
||||
fun setCrossfadeTarget(messageRecord: MmsMessageRecord) {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package org.thoughtcrime.securesms.stories.viewer.first
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.stories.StoryFirstTimeNavigationView
|
||||
import org.thoughtcrime.securesms.stories.viewer.StoryViewerState
|
||||
import org.thoughtcrime.securesms.stories.viewer.StoryViewerViewModel
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
|
||||
class StoryFirstTimeNavigationFragment : DialogFragment(R.layout.story_viewer_first_time_navigation_stub), StoryFirstTimeNavigationView.Callback {
|
||||
|
||||
private val viewModel: StoryViewerViewModel by viewModels(ownerProducer = {
|
||||
requireParentFragment()
|
||||
})
|
||||
|
||||
private val disposables = LifecycleDisposable()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_FRAME, R.style.Signal_DayNight_Dialog_FullScreen)
|
||||
isCancelable = false
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
dialog.window!!.addFlags(
|
||||
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION or
|
||||
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
|
||||
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
)
|
||||
}
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
(view as StoryFirstTimeNavigationView).show()
|
||||
view.callback = this
|
||||
viewModel.setIsDisplayingFirstTimeNavigation(true)
|
||||
|
||||
disposables += viewModel.state.subscribe { state ->
|
||||
when (state.crossfadeSource) {
|
||||
is StoryViewerState.CrossfadeSource.ImageUri -> {
|
||||
view.setBlurHash(state.crossfadeSource.imageBlur)
|
||||
}
|
||||
else -> {
|
||||
view.setBlurHash(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun userHasSeenFirstNavigationView(): Boolean {
|
||||
return SignalStore.storyValues().userHasSeenFirstNavView
|
||||
}
|
||||
|
||||
override fun onGotItClicked() {
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
SignalStore.storyValues().userHasSeenFirstNavView = true
|
||||
viewModel.setIsDisplayingFirstTimeNavigation(false)
|
||||
}
|
||||
|
||||
override fun onCloseClicked() {
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
if (viewModel.stateSnapshot.skipCrossfade) {
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
ActivityCompat.finishAfterTransition(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package org.thoughtcrime.securesms.stories.viewer.page
|
||||
|
||||
import android.view.ViewStub
|
||||
import androidx.core.view.isVisible
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHash
|
||||
import org.thoughtcrime.securesms.stories.StoryFirstTimeNavigationView
|
||||
import org.thoughtcrime.securesms.util.views.Stub
|
||||
|
||||
/**
|
||||
* Specialized stub that allows for early arrival of the blurhash and callback.
|
||||
*/
|
||||
class StoryFirstNavigationStub(viewStub: ViewStub) : Stub<StoryFirstTimeNavigationView>(viewStub) {
|
||||
|
||||
private var callback: StoryFirstTimeNavigationView.Callback? = null
|
||||
private var blurHash: BlurHash? = null
|
||||
|
||||
fun setCallback(callback: StoryFirstTimeNavigationView.Callback) {
|
||||
if (resolved()) {
|
||||
get().callback = callback
|
||||
} else {
|
||||
this.callback = callback
|
||||
}
|
||||
}
|
||||
|
||||
fun setBlurHash(blurHash: BlurHash?) {
|
||||
if (resolved()) {
|
||||
get().setBlurHash(blurHash)
|
||||
} else {
|
||||
this.blurHash = blurHash
|
||||
}
|
||||
}
|
||||
|
||||
fun showIfAble(ableToShow: Boolean) {
|
||||
if (ableToShow) {
|
||||
get().show()
|
||||
}
|
||||
}
|
||||
|
||||
fun isVisible(): Boolean {
|
||||
return resolved() && get().isVisible
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
if (resolved()) {
|
||||
get().hide()
|
||||
}
|
||||
}
|
||||
|
||||
override fun get(): StoryFirstTimeNavigationView {
|
||||
val needsResolve = !resolved()
|
||||
val view = super.get()
|
||||
if (needsResolve) {
|
||||
view.setBlurHash(blurHash)
|
||||
view.callback = callback
|
||||
blurHash = null
|
||||
callback = null
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
|
@ -6,11 +6,8 @@ import android.animation.ObjectAnimator
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.view.GestureDetector
|
||||
|
@ -55,14 +52,12 @@ import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectFor
|
|||
import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mediapreview.MediaPreviewFragment
|
||||
import org.thoughtcrime.securesms.mediapreview.VideoControlsDelegate
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
|
||||
import org.thoughtcrime.securesms.stories.StoryFirstTimeNavigationView
|
||||
import org.thoughtcrime.securesms.stories.StorySlateView
|
||||
import org.thoughtcrime.securesms.stories.StoryVolumeOverlayView
|
||||
import org.thoughtcrime.securesms.stories.dialogs.StoryContextMenu
|
||||
|
@ -97,7 +92,6 @@ class StoryViewerPageFragment :
|
|||
StoryPostFragment.Callback,
|
||||
MultiselectForwardBottomSheet.Callback,
|
||||
StorySlateView.Callback,
|
||||
StoryFirstTimeNavigationView.Callback,
|
||||
StoryInfoBottomSheetDialogFragment.OnInfoSheetDismissedListener,
|
||||
SafetyNumberBottomSheet.Callbacks {
|
||||
|
||||
|
@ -108,7 +102,7 @@ class StoryViewerPageFragment :
|
|||
private lateinit var viewsAndReplies: MaterialButton
|
||||
private lateinit var storyCaptionContainer: FrameLayout
|
||||
private lateinit var storyContentContainer: FrameLayout
|
||||
private lateinit var storyFirstTimeNavigationViewStub: StoryFirstNavigationStub
|
||||
private lateinit var storyPageContainer: ConstraintLayout
|
||||
private lateinit var sendingBarTextView: TextView
|
||||
private lateinit var sendingBar: View
|
||||
|
||||
|
@ -176,17 +170,16 @@ class StoryViewerPageFragment :
|
|||
val storyGradientBottom: View = view.findViewById(R.id.story_gradient_bottom)
|
||||
val storyVolumeOverlayView: StoryVolumeOverlayView = view.findViewById(R.id.story_volume_overlay)
|
||||
|
||||
storyPageContainer = view.findViewById(R.id.story_page_container)
|
||||
storyContentContainer = view.findViewById(R.id.story_content_container)
|
||||
storyCaptionContainer = view.findViewById(R.id.story_caption_container)
|
||||
storySlate = view.findViewById(R.id.story_slate)
|
||||
progressBar = view.findViewById(R.id.progress)
|
||||
viewsAndReplies = view.findViewById(R.id.views_and_replies_bar)
|
||||
storyFirstTimeNavigationViewStub = StoryFirstNavigationStub(view.findViewById(R.id.story_first_time_nav_stub))
|
||||
sendingBarTextView = view.findViewById(R.id.sending_text_view)
|
||||
sendingBar = view.findViewById(R.id.sending_bar)
|
||||
|
||||
storySlate.callback = this
|
||||
storyFirstTimeNavigationViewStub.setCallback(this)
|
||||
|
||||
chrome = listOf(
|
||||
closeView,
|
||||
|
@ -322,6 +315,10 @@ class StoryViewerPageFragment :
|
|||
viewModel.setIsUserScrollingChild(it)
|
||||
}
|
||||
|
||||
lifecycleDisposable += sharedViewModel.isFirstTimeNavigationShowing.subscribe {
|
||||
viewModel.setIsDisplayingFirstTimeNavigation(it)
|
||||
}
|
||||
|
||||
lifecycleDisposable += storyVolumeViewModel.state.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()).subscribe { volumeState ->
|
||||
if (volumeState.isMuted) {
|
||||
videoControlsDelegate.mute()
|
||||
|
@ -384,7 +381,6 @@ class StoryViewerPageFragment :
|
|||
presentDate(date, post)
|
||||
presentDistributionList(distributionList, post)
|
||||
presentCaption(caption, largeCaption, largeCaptionOverlay, post)
|
||||
presentBlur(post)
|
||||
|
||||
val durations: Map<Int, Long> = state.posts
|
||||
.mapIndexed { index, storyPost ->
|
||||
|
@ -428,37 +424,20 @@ class StoryViewerPageFragment :
|
|||
resumeProgress()
|
||||
}
|
||||
|
||||
val wasDisplayingNavigationView = storyFirstTimeNavigationViewStub.isVisible()
|
||||
|
||||
when {
|
||||
state.hideChromeImmediate -> {
|
||||
hideChromeImmediate()
|
||||
storyCaptionContainer.visible = false
|
||||
storyFirstTimeNavigationViewStub.hide()
|
||||
}
|
||||
state.hideChrome -> {
|
||||
hideChrome()
|
||||
storyCaptionContainer.visible = true
|
||||
storyFirstTimeNavigationViewStub.showIfAble(!SignalStore.storyValues().userHasSeenFirstNavView)
|
||||
}
|
||||
else -> {
|
||||
showChrome()
|
||||
storyCaptionContainer.visible = true
|
||||
storyFirstTimeNavigationViewStub.showIfAble(!SignalStore.storyValues().userHasSeenFirstNavView)
|
||||
}
|
||||
}
|
||||
|
||||
val isDisplayingNavigationView = storyFirstTimeNavigationViewStub.isVisible()
|
||||
if (isDisplayingNavigationView && Build.VERSION.SDK_INT >= 31) {
|
||||
hideChromeImmediate()
|
||||
storyContentContainer.setRenderEffect(RenderEffect.createBlurEffect(100f, 100f, Shader.TileMode.CLAMP))
|
||||
} else if (Build.VERSION.SDK_INT >= 31) {
|
||||
storyContentContainer.setRenderEffect(null)
|
||||
}
|
||||
|
||||
if (wasDisplayingNavigationView xor isDisplayingNavigationView) {
|
||||
viewModel.setIsDisplayingFirstTimeNavigation(storyFirstTimeNavigationViewStub.isVisible())
|
||||
}
|
||||
}
|
||||
|
||||
timeoutDisposable.bindTo(viewLifecycleOwner)
|
||||
|
@ -590,7 +569,7 @@ class StoryViewerPageFragment :
|
|||
card: CardView
|
||||
) {
|
||||
val constraintSet = ConstraintSet()
|
||||
constraintSet.clone(requireView() as ConstraintLayout)
|
||||
constraintSet.clone(storyPageContainer)
|
||||
|
||||
when (StoryDisplay.getStoryDisplay(resources.displayMetrics.widthPixels.toFloat(), resources.displayMetrics.heightPixels.toFloat())) {
|
||||
StoryDisplay.LARGE -> {
|
||||
|
@ -613,7 +592,7 @@ class StoryViewerPageFragment :
|
|||
}
|
||||
}
|
||||
|
||||
constraintSet.applyTo(requireView() as ConstraintLayout)
|
||||
constraintSet.applyTo(storyPageContainer)
|
||||
}
|
||||
|
||||
private fun resumeProgress() {
|
||||
|
@ -781,13 +760,6 @@ class StoryViewerPageFragment :
|
|||
distributionList.visible = storyPost.distributionList != null && !storyPost.distributionList.isMyStory
|
||||
}
|
||||
|
||||
private fun presentBlur(storyPost: StoryPost) {
|
||||
val record = storyPost.conversationMessage.messageRecord as? MediaMmsMessageRecord
|
||||
val blurHash = record?.slideDeck?.thumbnailSlide?.placeholderBlur
|
||||
|
||||
storyFirstTimeNavigationViewStub.setBlurHash(blurHash)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun presentCaption(caption: TextView, largeCaption: TextView, largeCaptionOverlay: View, storyPost: StoryPost) {
|
||||
val displayBody: String = if (storyPost.content is StoryPost.Content.AttachmentContent) {
|
||||
|
@ -1284,15 +1256,6 @@ class StoryViewerPageFragment :
|
|||
sharedViewModel.setContentIsReady()
|
||||
}
|
||||
|
||||
override fun userHasSeenFirstNavigationView(): Boolean {
|
||||
return SignalStore.storyValues().userHasSeenFirstNavView
|
||||
}
|
||||
|
||||
override fun onGotItClicked() {
|
||||
SignalStore.storyValues().userHasSeenFirstNavView = true
|
||||
viewModel.setIsDisplayingFirstTimeNavigation(false)
|
||||
}
|
||||
|
||||
override fun onInfoSheetDismissed() {
|
||||
viewModel.setIsDisplayingInfoDialog(false)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ data class StoryViewerPlaybackState(
|
|||
val isUserScaling: Boolean = false,
|
||||
val isDisplayingPartialSendDialog: Boolean = false
|
||||
) {
|
||||
val hideChromeImmediate: Boolean = isRunningSharedElementAnimation
|
||||
val hideChromeImmediate: Boolean = isRunningSharedElementAnimation || isDisplayingFirstTimeNavigation
|
||||
|
||||
val hideChrome: Boolean = isRunningSharedElementAnimation ||
|
||||
isUserLongTouching ||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
|
@ -2,6 +2,7 @@
|
|||
<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:id="@+id/story_page_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
|
@ -295,13 +296,4 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/story_first_time_nav_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:inflatedId="@+id/story_first_time_navigation_view"
|
||||
android:layout="@layout/story_viewer_first_time_navigation_stub"
|
||||
app:layout_constraintBottom_toBottomOf="@id/story_content_card_touch_interceptor"
|
||||
app:layout_constraintTop_toTopOf="@id/story_content_card_touch_interceptor" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -8,115 +8,95 @@
|
|||
<ImageView
|
||||
android:id="@+id/edu_blur_hash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no" />
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintDimensionRatio="9:16"
|
||||
app:tint="@color/core_white" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/edu_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@color/transparent_black_70" />
|
||||
android:src="@color/transparent_black_80" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/button_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="32dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_got_it"
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/edu_tap_icon"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_tap_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:lottie_rawRes="@raw/stories_tap_to_advance" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/edu_tap_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_up_icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/edu_tap_label"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_tap_72"
|
||||
app:tint="@color/core_white" />
|
||||
<TextView
|
||||
android:id="@+id/edu_tap_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/StoryFirstTimeNavigationView__tap_to_advance"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_up_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_tap_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/edu_tap_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/StoryFirstTimeNavigationView__tap_to_advance"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/edu_tap_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/edu_tap_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/edu_tap_icon" />
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/edu_swipe_up_icon"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_up_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_tap_label"
|
||||
app:lottie_rawRes="@raw/stories_swipe_up" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/edu_swipe_up_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_right_icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/edu_swipe_up_label"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_tap_icon"
|
||||
app:srcCompat="@drawable/ic_swipe_up_72"
|
||||
app:tint="@color/core_white" />
|
||||
<TextView
|
||||
android:id="@+id/edu_swipe_up_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/StoryFirstTimeNavigationView__swipe_up_to_skip"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_right_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_swipe_up_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/edu_swipe_up_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/StoryFirstTimeNavigationView__swipe_up_to_skip"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/edu_swipe_up_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/edu_swipe_up_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/edu_swipe_up_icon" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/edu_swipe_right_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/edu_swipe_right_label"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_swipe_up_icon"
|
||||
app:srcCompat="@drawable/ic_swipe_right_72"
|
||||
app:tint="@color/core_white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/edu_swipe_right_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/StoryFirstTimeNavigationView__swipe_right_to_exit"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/edu_swipe_right_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/edu_swipe_right_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/edu_swipe_right_icon" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/edu_swipe_right_icon"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/edu_swipe_right_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_swipe_up_label"
|
||||
app:lottie_rawRes="@raw/stories_swipe_right" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/edu_swipe_right_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/StoryFirstTimeNavigationView__swipe_right_to_exit"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_swipe_right_icon" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/edu_got_it"
|
||||
|
@ -129,6 +109,17 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_container" />
|
||||
app:layout_constraintTop_toBottomOf="@id/edu_swipe_right_label" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/edu_close"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="60dp"
|
||||
android:contentDescription="@string/Material3SearchToolbar__close"
|
||||
android:scaleType="centerInside"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_x_white" />
|
||||
</merge>
|
|
@ -2,8 +2,5 @@
|
|||
<org.thoughtcrime.securesms.stories.StoryFirstTimeNavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/story_content_card_touch_interceptor"
|
||||
app:layout_constraintTop_toTopOf="@id/story_content_card_touch_interceptor" />
|
||||
android:layout_height="match_parent" />
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -212,7 +212,7 @@
|
|||
|
||||
<style name="Signal.DayNight.Dialog.FullScreen.Donate">
|
||||
</style>
|
||||
|
||||
|
||||
<style name="Signal.Media.Dialog.AddMessageDialog" parent="TextSecure.MediaPreview">
|
||||
<item name="android:windowAnimationStyle">@style/TextSecure.Animation.AddMessageDialog</item>
|
||||
</style>
|
||||
|
|
|
@ -117,6 +117,7 @@ class StoryFirstTimeNavigationViewTest {
|
|||
testSubject.callback = object : StoryFirstTimeNavigationView.Callback {
|
||||
override fun userHasSeenFirstNavigationView(): Boolean = true
|
||||
override fun onGotItClicked() = error("Unused")
|
||||
override fun onCloseClicked() = error("Unused")
|
||||
}
|
||||
|
||||
testSubject.setBlurHash(BlurHash.parseOrNull("0000")!!)
|
||||
|
@ -150,6 +151,7 @@ class StoryFirstTimeNavigationViewTest {
|
|||
testSubject.callback = object : StoryFirstTimeNavigationView.Callback {
|
||||
override fun userHasSeenFirstNavigationView(): Boolean = true
|
||||
override fun onGotItClicked() = error("Unused")
|
||||
override fun onCloseClicked() = error("Unused")
|
||||
}
|
||||
|
||||
testSubject.show()
|
||||
|
|
Ładowanie…
Reference in New Issue