diff --git a/app/src/main/java/org/thoughtcrime/securesms/animation/transitions/FabElevationFadeTransform.kt b/app/src/main/java/org/thoughtcrime/securesms/animation/transitions/FabElevationFadeTransform.kt index f5be57cd1..db37c5c35 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/animation/transitions/FabElevationFadeTransform.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/animation/transitions/FabElevationFadeTransform.kt @@ -3,15 +3,14 @@ package org.thoughtcrime.securesms.animation.transitions import android.animation.Animator import android.animation.ValueAnimator import android.content.Context -import android.transition.Transition -import android.transition.TransitionValues import android.util.AttributeSet import android.view.ViewGroup -import androidx.annotation.RequiresApi +import androidx.core.view.ViewCompat +import androidx.transition.Transition +import androidx.transition.TransitionValues import com.google.android.material.floatingactionbutton.FloatingActionButton -@RequiresApi(21) -class FabElevationFadeTransform(context: Context, attrs: AttributeSet?) : Transition(context, attrs) { +class FabElevationFadeTransform(context: Context, attrs: AttributeSet) : Transition(context, attrs) { companion object { private const val ELEVATION = "CrossfaderTransition.ELEVATION" @@ -19,23 +18,23 @@ class FabElevationFadeTransform(context: Context, attrs: AttributeSet?) : Transi override fun captureStartValues(transitionValues: TransitionValues) { if (transitionValues.view is FloatingActionButton) { - transitionValues.values[ELEVATION] = transitionValues.view.elevation + transitionValues.values[ELEVATION] = ViewCompat.getElevation(transitionValues.view) } } override fun captureEndValues(transitionValues: TransitionValues) { if (transitionValues.view is FloatingActionButton) { - transitionValues.values[ELEVATION] = transitionValues.view.elevation + transitionValues.values[ELEVATION] = ViewCompat.getElevation(transitionValues.view) } } - override fun createAnimator(sceneRoot: ViewGroup?, startValues: TransitionValues?, endValues: TransitionValues?): Animator? { + override fun createAnimator(sceneRoot: ViewGroup, startValues: TransitionValues?, endValues: TransitionValues?): Animator? { if (startValues?.view !is FloatingActionButton || endValues?.view !is FloatingActionButton) { return null } - val startElevation = startValues.view.elevation - val endElevation = endValues.view.elevation + val startElevation = ViewCompat.getElevation(startValues.view) + val endElevation = ViewCompat.getElevation(endValues.view) if (startElevation == endElevation) { return null } @@ -46,7 +45,7 @@ class FabElevationFadeTransform(context: Context, attrs: AttributeSet?) : Transi ).apply { addUpdateListener { val elevation = it.animatedValue as Float - endValues.view.elevation = elevation + ViewCompat.setElevation(endValues.view, elevation) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/main/MainActivityListHostFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/main/MainActivityListHostFragment.kt index fd223bded..e9c0d1922 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/main/MainActivityListHostFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/main/MainActivityListHostFragment.kt @@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.ActionMenuView import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat import androidx.core.view.children import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels @@ -108,6 +109,9 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f val cameraFab = requireView().findViewById(R.id.camera_fab) val newConvoFab = requireView().findViewById(R.id.fab) + ViewCompat.setTransitionName(cameraFab, "camera_fab") + ViewCompat.setTransitionName(newConvoFab, "new_convo_fab") + val extras: Navigator.Extras? = if (cameraFab == null || newConvoFab == null) { null } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingFragment.kt index a5c6e544c..552881b01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingFragment.kt @@ -4,7 +4,6 @@ import android.Manifest import android.content.Intent import android.net.Uri import android.os.Bundle -import android.transition.TransitionInflater import android.view.Menu import android.view.MenuInflater import android.view.MenuItem @@ -16,6 +15,7 @@ import androidx.core.app.SharedElementCallback import androidx.core.view.ViewCompat import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager +import androidx.transition.TransitionInflater import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers @@ -129,6 +129,10 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l lifecycleDisposable.bindTo(viewLifecycleOwner) emptyNotice = requireView().findViewById(R.id.empty_notice) cameraFab = requireView().findViewById(R.id.camera_fab) + val sharedElementTarget: View = requireView().findViewById(R.id.camera_fab_shared_element_target) + + ViewCompat.setTransitionName(cameraFab, "new_convo_fab") + ViewCompat.setTransitionName(sharedElementTarget, "camera_fab") sharedElementEnterTransition = TransitionInflater.from(requireContext()).inflateTransition(R.transition.change_transform_fabs) setEnterSharedElementCallback(object : SharedElementCallback() { @@ -139,6 +143,7 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l .observeOn(AndroidSchedulers.mainThread()) .subscribeBy { cameraFab.setImageResource(R.drawable.ic_camera_outline_24) + sharedElementTarget.alpha = 0f } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingItem.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingItem.kt index cac84e2de..729a59600 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingItem.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/landing/StoriesLandingItem.kt @@ -7,6 +7,7 @@ import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener @@ -116,6 +117,7 @@ object StoriesLandingItem { private val badgeView: BadgeImageView = itemView.findViewById(R.id.badge) private val storyPreview: ImageView = itemView.findViewById(R.id.story).apply { isClickable = false + ViewCompat.setTransitionName(this, "story") } private val storyBlur: ImageView = itemView.findViewById(R.id.story_blur).apply { isClickable = false diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerFragment.kt index 6b5428ea2..3bce26e99 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerFragment.kt @@ -6,6 +6,7 @@ import android.os.Build import android.os.Bundle import android.view.View import androidx.core.app.ActivityCompat +import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.viewpager2.widget.ViewPager2 @@ -51,6 +52,7 @@ class StoryViewerFragment : storyCrossfader = view.findViewById(R.id.story_content_crossfader) storyPager = view.findViewById(R.id.story_item_pager) + ViewCompat.setTransitionName(storyCrossfader, "story") storyCrossfader.callback = this val adapter = StoryViewerPagerAdapter( diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt index 0389075d2..686f8be09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.stories.viewer +import android.os.Build import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -30,7 +31,7 @@ class StoryViewerViewModel( storyViewerArgs.storyThumbUri != null -> StoryViewerState.CrossfadeSource.ImageUri(storyViewerArgs.storyThumbUri, storyViewerArgs.storyThumbBlur) else -> StoryViewerState.CrossfadeSource.None }, - skipCrossfade = storyViewerArgs.isFromNotification || storyViewerArgs.isFromQuote + skipCrossfade = storyViewerArgs.isFromNotification || storyViewerArgs.isFromQuote || Build.VERSION.SDK_INT < 21 ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/first/StoryFirstTimeNavigationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/first/StoryFirstTimeNavigationFragment.kt index f486d56e0..9e5026938 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/first/StoryFirstTimeNavigationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/first/StoryFirstTimeNavigationFragment.kt @@ -10,6 +10,7 @@ import android.view.WindowManager import androidx.core.app.ActivityCompat import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.stories.StoryFirstTimeNavigationView @@ -51,7 +52,7 @@ class StoryFirstTimeNavigationFragment : DialogFragment(R.layout.story_viewer_fi view.callback = this viewModel.setIsDisplayingFirstTimeNavigation(true) - disposables += viewModel.state.subscribe { state -> + disposables += viewModel.state.observeOn(AndroidSchedulers.mainThread()).subscribe { state -> when (state.crossfadeSource) { is StoryViewerState.CrossfadeSource.ImageUri -> { view.setBlurHash(state.crossfadeSource.imageBlur) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/adapter/mapping/LayoutFactory.java b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/mapping/LayoutFactory.java index 438bb89e1..731c32fb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/adapter/mapping/LayoutFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/mapping/LayoutFactory.java @@ -7,6 +7,8 @@ import android.view.ViewGroup; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; +import org.signal.core.util.logging.Log; + import java.util.function.Function; diff --git a/app/src/main/res/drawable/stories_my_story_add_background.xml b/app/src/main/res/drawable/stories_my_story_add_background.xml index fa517b5d5..83efb6b6c 100644 --- a/app/src/main/res/drawable/stories_my_story_add_background.xml +++ b/app/src/main/res/drawable/stories_my_story_add_background.xml @@ -1,11 +1,5 @@ - - - + + + + + \ No newline at end of file