Media Preview V2 Visual Redesign.

main
Nicholas 2022-10-25 15:22:38 -04:00 zatwierdzone przez Alex Hart
rodzic b8174c5e00
commit 7759ad283d
21 zmienionych plików z 339 dodań i 230 usunięć

Wyświetl plik

@ -5,7 +5,6 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -16,7 +15,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.MediaUtil;
public final class ImageMediaPreviewFragment extends MediaPreviewFragment { public final class ImageMediaPreviewFragment extends MediaPreviewFragment {
private View bottomBarControlView; private MediaPreviewPlayerControlView bottomBarControlView;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -41,26 +40,24 @@ public final class ImageMediaPreviewFragment extends MediaPreviewFragment {
zoomingImageView.setOnClickListener(v -> events.singleTapOnMedia()); zoomingImageView.setOnClickListener(v -> events.singleTapOnMedia());
bottomBarControlView = getLayoutInflater().inflate(R.layout.image_media_preview_bottom_bar, null);
return zoomingImageView; return zoomingImageView;
} }
@Override @Override
public void setShareButtonListener(View.OnClickListener listener) { public void cleanUp() {
ImageButton forwardButton = bottomBarControlView.findViewById(R.id.image_preview_forward); bottomBarControlView = null;
forwardButton.setOnClickListener(listener);
} }
@Override @Override
public void setForwardButtonListener(View.OnClickListener listener) { public void pause() {}
ImageButton shareButton = bottomBarControlView.findViewById(R.id.image_preview_share);
shareButton.setOnClickListener(listener);
}
@Nullable
@Override @Override
public View getBottomBarControls() { public ViewGroup getBottomBarControls() {
return bottomBarControlView; return bottomBarControlView;
} }
@Override
public void setBottomButtonControls(MediaPreviewPlayerControlView playerControlView) {
bottomBarControlView = playerControlView;
}
} }

Wyświetl plik

@ -3,14 +3,12 @@ package org.thoughtcrime.securesms.mediapreview;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.exoplayer2.ui.PlayerControlView;
import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId; import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
@ -81,15 +79,10 @@ public abstract class MediaPreviewFragment extends Fragment {
checkMediaStillAvailable(); checkMediaStillAvailable();
} }
public void cleanUp() { public abstract void cleanUp();
} public abstract void pause();
public abstract ViewGroup getBottomBarControls();
public void pause() { public abstract void setBottomButtonControls(MediaPreviewPlayerControlView playerControlView);
}
abstract public void setShareButtonListener(View.OnClickListener listener);
abstract public void setForwardButtonListener(View.OnClickListener listener);
abstract public @Nullable View getBottomBarControls();
private void checkMediaStillAvailable() { private void checkMediaStillAvailable() {
if (attachmentId == null) { if (attachmentId == null) {

Wyświetl plik

@ -0,0 +1,58 @@
package org.thoughtcrime.securesms.mediapreview
import android.content.Context
import android.util.AttributeSet
import android.widget.ImageButton
import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.android.exoplayer2.ui.PlayerControlView
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.MediaUtil
/**
* The bottom bar for the media preview. This includes the standard seek bar as well as playback controls,
* but adds forward and share buttons as well as a recyclerview that can be populated with a rail of thumbnails.
*/
class MediaPreviewPlayerControlView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
playbackAttrs: AttributeSet? = null
) : PlayerControlView(context, attrs, defStyleAttr, playbackAttrs) {
val recyclerView: RecyclerView = findViewById(R.id.media_preview_album_rail)
private val durationBar: LinearLayout = findViewById(R.id.exo_duration_viewgroup)
private val videoControls: LinearLayout = findViewById(R.id.exo_button_viewgroup)
private val shareButton: ImageButton = findViewById(R.id.exo_share)
private val forwardButton: ImageButton = findViewById(R.id.exo_forward)
enum class MediaMode {
IMAGE, VIDEO;
companion object {
@JvmStatic
fun fromString(contentType: String): MediaMode {
if (MediaUtil.isVideo(contentType)) return VIDEO
if (MediaUtil.isImageType(contentType)) return IMAGE
throw IllegalArgumentException("Unknown content type: $contentType")
}
}
}
init {
setShowPreviousButton(false)
setShowNextButton(false)
showShuffleButton = false
showVrButton = false
showTimeoutMs = -1
}
fun setVisibility(mediaMode: MediaMode) {
durationBar.visibility = if (mediaMode == MediaMode.VIDEO) VISIBLE else GONE
videoControls.visibility = if (mediaMode == MediaMode.VIDEO) VISIBLE else INVISIBLE
}
fun setShareButtonListener(listener: OnClickListener?) = shareButton.setOnClickListener(listener)
fun setForwardButtonListener(listener: OnClickListener?) = forwardButton.setOnClickListener(listener)
}

Wyświetl plik

@ -20,7 +20,7 @@ class MediaPreviewV2Activity : AppCompatActivity(R.layout.activity_mediapreview_
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setTheme(R.style.TextSecure_MediaPreview) setTheme(R.style.TextSecure_MediaPreview)
if (Build.VERSION.SDK_INT >= 21) { if (Build.VERSION.SDK_INT >= 21) {
val systemBarColor = ContextCompat.getColor(this, R.color.media_preview_bar_background) val systemBarColor = ContextCompat.getColor(this, R.color.signal_dark_colorSurface)
window.statusBarColor = systemBarColor window.statusBarColor = systemBarColor
window.navigationBarColor = systemBarColor window.navigationBarColor = systemBarColor
} }

Wyświetl plik

@ -18,7 +18,7 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT import androidx.viewpager2.widget.ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
@ -72,12 +72,10 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val args = MediaIntentFactory.requireArguments(requireArguments()) val args = MediaIntentFactory.requireArguments(requireArguments())
initializeViewModel(args) initializeViewModel(args)
initializeToolbar(binding.toolbar) initializeToolbar(binding.toolbar)
initializeViewPager() initializeViewPager()
initializeFullScreenUi() initializeFullScreenUi()
initializeAlbumRail()
anchorMarginsToBottomInsets(binding.mediaPreviewDetailsContainer) anchorMarginsToBottomInsets(binding.mediaPreviewDetailsContainer)
lifecycleDisposable += viewModel.state.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()).subscribe { lifecycleDisposable += viewModel.state.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()).subscribe {
bindCurrentState(it) bindCurrentState(it)
@ -92,10 +90,7 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
requireActivity().finish() requireActivity().finish()
}.show() }.show()
} }
viewModel.initialize(args.showThread, args.allMediaInRail, args.leftIsRecent)
viewModel.setShowThread(args.showThread)
viewModel.setAlwaysShowAlbumRail(args.allMediaInRail)
viewModel.setLeftIsRecent(args.leftIsRecent)
val sorting = MediaDatabase.Sorting.deserialize(args.sorting) val sorting = MediaDatabase.Sorting.deserialize(args.sorting)
viewModel.fetchAttachments(PartAuthority.requireAttachmentId(args.initialMediaUri), args.threadId, sorting) viewModel.fetchAttachments(PartAuthority.requireAttachmentId(args.initialMediaUri), args.threadId, sorting)
} }
@ -105,6 +100,8 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
requireActivity().onBackPressed() requireActivity().onBackPressed()
} }
toolbar.setTitleTextAppearance(requireContext(), R.style.Signal_Text_TitleMedium)
toolbar.setSubtitleTextAppearance(requireContext(), R.style.Signal_Text_BodyMedium)
binding.toolbar.inflateMenu(R.menu.media_preview) binding.toolbar.inflateMenu(R.menu.media_preview)
} }
@ -123,10 +120,9 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
}) })
} }
private fun initializeAlbumRail() { private fun initializeAlbumRail(recyclerView: RecyclerView, albumThumbnailMedia: List<Media?>, albumPosition: Int) {
binding.mediaPreviewAlbumRail.itemAnimator = null // Or can crash when set to INVISIBLE while animating by FullscreenHelper https://issuetracker.google.com/issues/148720682 recyclerView.itemAnimator = null // Or can crash when set to INVISIBLE while animating by FullscreenHelper https://issuetracker.google.com/issues/148720682
binding.mediaPreviewAlbumRail.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) val mediaRailAdapter = MediaRailAdapter(
binding.mediaPreviewAlbumRail.adapter = MediaRailAdapter(
GlideApp.with(this), GlideApp.with(this),
object : MediaRailAdapter.RailItemListener { object : MediaRailAdapter.RailItemListener {
override fun onRailItemClicked(distanceFromActive: Int) { override fun onRailItemClicked(distanceFromActive: Int) {
@ -139,6 +135,9 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
}, },
false false
) )
mediaRailAdapter.setMedia(albumThumbnailMedia, albumPosition)
recyclerView.adapter = mediaRailAdapter
recyclerView.smoothScrollToPosition(albumPosition)
} }
private fun initializeFullScreenUi() { private fun initializeFullScreenUi() {
@ -152,21 +151,43 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
return return
} }
when (currentState.loadState) { when (currentState.loadState) {
MediaPreviewV2State.LoadState.READY -> bindReadyState(currentState) MediaPreviewV2State.LoadState.DATA_LOADED -> bindDataLoadedState(currentState)
MediaPreviewV2State.LoadState.LOADED -> { MediaPreviewV2State.LoadState.MEDIA_READY -> bindMediaReadyState(currentState)
bindReadyState(currentState)
bindLoadedState(currentState)
}
else -> null else -> null
} }
} }
private fun bindReadyState(currentState: MediaPreviewV2State) { private fun bindDataLoadedState(currentState: MediaPreviewV2State) {
(binding.mediaPager.adapter as MediaPreviewV2Adapter).updateBackingItems(currentState.mediaRecords.mapNotNull { it.attachment }) (binding.mediaPager.adapter as MediaPreviewV2Adapter).updateBackingItems(currentState.mediaRecords.mapNotNull { it.attachment })
if (binding.mediaPager.currentItem != currentState.position) { val currentPosition = currentState.position
binding.mediaPager.setCurrentItem(currentState.position, false) if (binding.mediaPager.currentItem != currentPosition) {
binding.mediaPager.setCurrentItem(currentPosition, false)
} }
val currentItem: MediaDatabase.MediaRecord = currentState.mediaRecords[currentState.position] }
/**
* These are binding steps that need a reference to the actual fragment within the pager.
* This is not available until after a page has been chosen by the ViewPager, and we receive the
* {@link OnPageChangeCallback}.
*/
private fun bindMediaReadyState(currentState: MediaPreviewV2State) {
val currentPosition = currentState.position
val currentItem: MediaDatabase.MediaRecord = currentState.mediaRecords[currentPosition]
// pause all other fragments
childFragmentManager.fragments.map { fragment ->
if (fragment.tag != "f$currentPosition") {
(fragment as? MediaPreviewFragment)?.pause()
}
}
val mediaType: MediaPreviewPlayerControlView.MediaMode = if (currentItem.attachment?.isVideoGif == true) {
MediaPreviewPlayerControlView.MediaMode.IMAGE
} else {
MediaPreviewPlayerControlView.MediaMode.fromString(currentItem.contentType)
}
binding.mediaPreviewPlaybackControls.setVisibility(mediaType)
binding.toolbar.title = getTitleText(currentItem, currentState.showThread) binding.toolbar.title = getTitleText(currentItem, currentState.showThread)
binding.toolbar.subtitle = getSubTitleText(currentItem) binding.toolbar.subtitle = getSubTitleText(currentItem)
@ -184,16 +205,6 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
} }
return@setOnMenuItemClickListener true return@setOnMenuItemClickListener true
} }
}
/**
* These are binding steps that need a reference to the actual fragment within the pager.
* This is not available until after a page has been chosen by the ViewPager, and we receive the
* {@link OnPageChangeCallback}.
*/
private fun bindLoadedState(currentState: MediaPreviewV2State) {
val currentItem: MediaDatabase.MediaRecord = currentState.mediaRecords[currentState.position]
val albumThumbnailMedia = if (currentState.allMediaInAlbumRail) { val albumThumbnailMedia = if (currentState.allMediaInAlbumRail) {
currentState.mediaRecords.map { it.toMedia() } currentState.mediaRecords.map { it.toMedia() }
} else { } else {
@ -201,11 +212,10 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
.filter { it.attachment != null && it.attachment!!.mmsId == currentItem.attachment?.mmsId } .filter { it.attachment != null && it.attachment!!.mmsId == currentItem.attachment?.mmsId }
.map { it.toMedia() } .map { it.toMedia() }
} }
val caption = currentItem.attachment?.caption val caption = currentItem.attachment?.caption
binding.mediaPreviewAlbumRail.visibility = if (albumThumbnailMedia.size <= 1) View.GONE else View.VISIBLE val albumRailEnabled = albumThumbnailMedia.size > 1
(binding.mediaPreviewAlbumRail.adapter as MediaRailAdapter).setMedia(albumThumbnailMedia, currentState.position)
binding.mediaPreviewAlbumRail.smoothScrollToPosition(currentState.position)
if (caption != null) { if (caption != null) {
binding.mediaPreviewCaption.text = caption binding.mediaPreviewCaption.text = caption
@ -214,24 +224,21 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
binding.mediaPreviewCaption.visibility = View.GONE binding.mediaPreviewCaption.visibility = View.GONE
} }
val fragmentTag = "f${currentState.position}" binding.mediaPreviewPlaybackControls.setShareButtonListener { share(currentItem) }
val currentFragment: MediaPreviewFragment? = childFragmentManager.findFragmentByTag(fragmentTag) as? MediaPreviewFragment binding.mediaPreviewPlaybackControls.setForwardButtonListener { forward(currentItem) }
val playbackControls: View? = currentFragment?.bottomBarControls
if (albumThumbnailMedia.size <= 1 && caption == null && playbackControls == null) { val albumRail: RecyclerView = binding.mediaPreviewPlaybackControls.findViewById(R.id.media_preview_album_rail)
binding.mediaPreviewDetailsContainer.visibility = View.GONE if (albumRailEnabled) {
} else { val albumPosition = albumThumbnailMedia.indexOfFirst { it?.uri == currentItem.attachment?.uri }
binding.mediaPreviewDetailsContainer.visibility = View.VISIBLE initializeAlbumRail(albumRail, albumThumbnailMedia, albumPosition)
} }
binding.mediaPreviewPlaybackControlsContainer.removeAllViews() albumRail.visibility = if (albumRailEnabled) View.VISIBLE else View.GONE
if (playbackControls != null) { val currentFragment: MediaPreviewFragment? = getMediaPreviewFragmentFromChildFragmentManager(currentPosition)
val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) currentFragment?.setBottomButtonControls(binding.mediaPreviewPlaybackControls)
playbackControls.layoutParams = params
binding.mediaPreviewPlaybackControlsContainer.addView(playbackControls)
}
currentFragment?.setShareButtonListener { share(currentItem) }
currentFragment?.setForwardButtonListener { forward(currentItem) }
} }
private fun getMediaPreviewFragmentFromChildFragmentManager(currentPosition: Int) = childFragmentManager.findFragmentByTag("f$currentPosition") as? MediaPreviewFragment
private fun getTitleText(mediaRecord: MediaDatabase.MediaRecord, showThread: Boolean): String { private fun getTitleText(mediaRecord: MediaDatabase.MediaRecord, showThread: Boolean): String {
val recipient: Recipient = Recipient.live(mediaRecord.recipientId).get() val recipient: Recipient = Recipient.live(mediaRecord.recipientId).get()
val defaultFromString: String = if (mediaRecord.isOutgoing) { val defaultFromString: String = if (mediaRecord.isOutgoing) {
@ -315,7 +322,7 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
} }
override fun onMediaReady() { override fun onMediaReady() {
Log.d(TAG, "onMediaReady()") viewModel.setMediaReady()
} }
private fun forward(mediaItem: MediaDatabase.MediaRecord) { private fun forward(mediaItem: MediaDatabase.MediaRecord) {
@ -400,6 +407,11 @@ class MediaPreviewV2Fragment : Fragment(R.layout.fragment_media_preview_v2), Med
.show() .show()
} }
override fun onPause() {
super.onPause()
getMediaPreviewFragmentFromChildFragmentManager(binding.mediaPager.currentItem)?.pause()
}
companion object { companion object {
const val ARGS_KEY: String = "args" const val ARGS_KEY: String = "args"
} }

Wyświetl plik

@ -8,7 +8,7 @@ data class MediaPreviewV2State(
val position: Int = 0, val position: Int = 0,
val showThread: Boolean = false, val showThread: Boolean = false,
val allMediaInAlbumRail: Boolean = false, val allMediaInAlbumRail: Boolean = false,
val leftIsRecent: Boolean = false val leftIsRecent: Boolean = false,
) { ) {
enum class LoadState { INIT, READY, LOADED } enum class LoadState { INIT, DATA_LOADED, MEDIA_READY }
} }

Wyświetl plik

@ -24,46 +24,44 @@ class MediaPreviewV2ViewModel : ViewModel() {
val state: Flowable<MediaPreviewV2State> = store.stateFlowable.observeOn(AndroidSchedulers.mainThread()) val state: Flowable<MediaPreviewV2State> = store.stateFlowable.observeOn(AndroidSchedulers.mainThread())
fun fetchAttachments(startingAttachmentId: AttachmentId, threadId: Long, sorting: MediaDatabase.Sorting) { fun fetchAttachments(startingAttachmentId: AttachmentId, threadId: Long, sorting: MediaDatabase.Sorting, forceRefresh: Boolean = false) {
if (store.state.loadState == MediaPreviewV2State.LoadState.INIT || forceRefresh) {
disposables += store.update(repository.getAttachments(startingAttachmentId, threadId, sorting)) { disposables += store.update(repository.getAttachments(startingAttachmentId, threadId, sorting)) {
result: MediaPreviewRepository.Result, oldState: MediaPreviewV2State -> result: MediaPreviewRepository.Result, oldState: MediaPreviewV2State ->
if (oldState.leftIsRecent) { if (oldState.leftIsRecent) {
oldState.copy( oldState.copy(
position = result.initialPosition, position = result.initialPosition,
mediaRecords = result.records, mediaRecords = result.records,
loadState = MediaPreviewV2State.LoadState.READY, loadState = MediaPreviewV2State.LoadState.DATA_LOADED,
) )
} else { } else {
oldState.copy( oldState.copy(
position = result.records.size - result.initialPosition - 1, position = result.records.size - result.initialPosition - 1,
mediaRecords = result.records.reversed(), mediaRecords = result.records.reversed(),
loadState = MediaPreviewV2State.LoadState.READY, loadState = MediaPreviewV2State.LoadState.DATA_LOADED,
) )
} }
} }
} }
fun setShowThread(value: Boolean) {
store.update { oldState ->
oldState.copy(showThread = value)
}
} }
fun setAlwaysShowAlbumRail(value: Boolean) { fun initialize(showThread: Boolean, allMediaInAlbumRail: Boolean, leftIsRecent: Boolean) {
if (store.state.loadState == MediaPreviewV2State.LoadState.INIT) {
store.update { oldState -> store.update { oldState ->
oldState.copy(allMediaInAlbumRail = value) oldState.copy(showThread = showThread, allMediaInAlbumRail = allMediaInAlbumRail, leftIsRecent = leftIsRecent)
} }
} }
fun setLeftIsRecent(value: Boolean) {
store.update { oldState ->
oldState.copy(leftIsRecent = value)
}
} }
fun setCurrentPage(position: Int) { fun setCurrentPage(position: Int) {
store.update { oldState -> store.update { oldState ->
oldState.copy(position = position, loadState = MediaPreviewV2State.LoadState.LOADED) oldState.copy(position = position)
}
}
fun setMediaReady() {
store.update { oldState ->
oldState.copy(loadState = MediaPreviewV2State.LoadState.MEDIA_READY)
} }
} }

Wyświetl plik

@ -6,7 +6,6 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -30,8 +29,6 @@ public final class VideoMediaPreviewFragment extends MediaPreviewFragment {
private VideoPlayer videoView; private VideoPlayer videoView;
private boolean isVideoGif; private boolean isVideoGif;
private ImageButton shareButton;
private ImageButton forwardButton;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -90,21 +87,15 @@ public final class VideoMediaPreviewFragment extends MediaPreviewFragment {
}); });
if (isVideoGif) { if (isVideoGif) {
videoView.hideControls();
videoView.loopForever(); videoView.loopForever();
} }
videoView.setOnClickListener(v -> events.singleTapOnMedia()); videoView.setOnClickListener(v -> events.singleTapOnMedia());
final PlayerControlView controlView = videoView.getControlView();
if (controlView != null) {
shareButton = controlView.findViewById(R.id.exo_share);
forwardButton = controlView.findViewById(R.id.exo_forward);
}
return itemView; return itemView;
} }
private void updateSkipButtonState() { private void updateSkipButtonState() {
final PlayerControlView playbackControls = getBottomBarControls(); final PlayerControlView playbackControls = videoView.getControlView();
if (playbackControls != null) { if (playbackControls != null) {
boolean shouldShowSkipButtons = videoView.getDuration() > MINIMUM_DURATION_FOR_SKIP_MS; boolean shouldShowSkipButtons = videoView.getDuration() > MINIMUM_DURATION_FOR_SKIP_MS;
playbackControls.setShowFastForwardButton(shouldShowSkipButtons); playbackControls.setShowFastForwardButton(shouldShowSkipButtons);
@ -149,20 +140,16 @@ public final class VideoMediaPreviewFragment extends MediaPreviewFragment {
} }
} }
@Override
public void setShareButtonListener(View.OnClickListener listener) {
shareButton.setOnClickListener(listener);
}
@Override
public void setForwardButtonListener(View.OnClickListener listener) {
forwardButton.setOnClickListener(listener);
}
@Nullable @Nullable
@Override @Override
public PlayerControlView getBottomBarControls() { public MediaPreviewPlayerControlView getBottomBarControls() {
return videoView != null && !isVideoGif ? videoView.getControlView() : null; return (MediaPreviewPlayerControlView) videoView.getControlView();
}
@Override
public void setBottomButtonControls(@NonNull MediaPreviewPlayerControlView playerControlView) {
videoView.setControlView(playerControlView);
updateSkipButtonState();
} }
private @NonNull Uri getUri() { private @NonNull Uri getUri() {

Wyświetl plik

@ -19,15 +19,12 @@ package org.thoughtcrime.securesms.video;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.res.TypedArrayKt;
import androidx.core.content.res.TypedArrayUtils;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
@ -45,6 +42,7 @@ import com.google.android.exoplayer2.ui.PlayerView;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewPlayerControlView;
import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.mms.VideoSlide;
import java.util.Objects; import java.util.Objects;
@ -56,10 +54,10 @@ public class VideoPlayer extends FrameLayout {
private static final String TAG = Log.tag(VideoPlayer.class); private static final String TAG = Log.tag(VideoPlayer.class);
private final PlayerView exoView; private final PlayerView exoView;
private final PlayerControlView exoControls;
private final DefaultMediaSourceFactory mediaSourceFactory; private final DefaultMediaSourceFactory mediaSourceFactory;
private ExoPlayer exoPlayer; private ExoPlayer exoPlayer;
private PlayerControlView exoControls;
private Window window; private Window window;
private PlayerStateCallback playerStateCallback; private PlayerStateCallback playerStateCallback;
private PlayerPositionDiscontinuityCallback playerPositionDiscontinuityCallback; private PlayerPositionDiscontinuityCallback playerPositionDiscontinuityCallback;
@ -233,6 +231,11 @@ public class VideoPlayer extends FrameLayout {
return this.exoControls; return this.exoControls;
} }
public void setControlView(MediaPreviewPlayerControlView controller) {
exoControls = controller;
exoControls.setPlayer(exoPlayer);
}
public void stop() { public void stop() {
if (this.exoPlayer != null) { if (this.exoPlayer != null) {
exoPlayer.stop(); exoPlayer.stop();

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
<path
android:pathData="M4.513,10.8L3.875,10.164L8.029,6L3.875,1.835L4.513,1.2L9.3,6L4.513,10.8Z"
android:fillColor="@color/core_white"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M4,20.5H20V22H4V20.5ZM20.65,10.35L12,19L3.35,10.35C3.281,10.28 3.234,10.19 3.216,10.093C3.197,9.996 3.208,9.896 3.247,9.805C3.285,9.714 3.35,9.637 3.432,9.582C3.515,9.528 3.611,9.499 3.71,9.5H8V3H16V9.5H20.29C21,9.5 21.12,9.88 20.65,10.35ZM17.88,11H14.5V4.5H9.5V11H6.12L12,16.88L17.88,11Z"
android:fillColor="#000000"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M15.622,8.813C16.688,8.813 17.59,8.126 17.939,7.183H21.487C21.907,7.183 22.276,6.813 22.276,6.352C22.276,5.891 21.907,5.532 21.487,5.532H17.939C17.601,4.578 16.688,3.881 15.622,3.881C14.555,3.881 13.632,4.578 13.294,5.532H2.435C1.974,5.532 1.615,5.891 1.615,6.352C1.615,6.813 1.974,7.183 2.435,7.183H13.304C13.643,8.126 14.555,8.813 15.622,8.813ZM15.622,7.552C14.945,7.552 14.422,7.019 14.422,6.342C14.422,5.665 14.945,5.142 15.622,5.142C16.298,5.142 16.821,5.665 16.821,6.342C16.821,7.019 16.298,7.552 15.622,7.552ZM2.394,11.787C1.974,11.787 1.615,12.156 1.615,12.617C1.615,13.079 1.974,13.438 2.394,13.438H6.065C6.403,14.401 7.316,15.088 8.382,15.088C9.449,15.088 10.361,14.401 10.71,13.438H21.446C21.907,13.438 22.276,13.079 22.276,12.617C22.276,12.156 21.907,11.787 21.446,11.787H10.7C10.361,10.843 9.449,10.156 8.382,10.156C7.316,10.156 6.403,10.843 6.065,11.787H2.394ZM8.382,13.817C7.716,13.817 7.183,13.284 7.183,12.617C7.183,11.94 7.716,11.417 8.382,11.417C9.059,11.417 9.582,11.94 9.582,12.617C9.582,13.284 9.059,13.817 8.382,13.817ZM15.622,21.343C16.688,21.343 17.601,20.656 17.939,19.703H21.487C21.907,19.703 22.276,19.344 22.276,18.882C22.276,18.421 21.907,18.052 21.487,18.052H17.939C17.601,17.098 16.688,16.421 15.622,16.421C14.555,16.421 13.643,17.098 13.304,18.052H2.435C1.974,18.052 1.615,18.421 1.615,18.882C1.615,19.344 1.974,19.703 2.435,19.703H13.294C13.643,20.656 14.555,21.343 15.622,21.343ZM15.622,20.082C14.945,20.082 14.422,19.549 14.422,18.882C14.422,18.195 14.945,17.683 15.622,17.683C16.298,17.683 16.821,18.195 16.821,18.882C16.821,19.549 16.298,20.082 15.622,20.082Z"
android:fillColor="#000000"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M14.521,5.621V9.321L13.212,9.49C11.119,9.672 9.123,10.452 7.462,11.738C5.801,13.025 4.546,14.762 3.847,16.743C3.687,17.149 3.047,18.499 3.047,18.499C3.516,18.041 4.007,17.607 4.52,17.199C7.039,15.597 9.926,14.668 12.906,14.5L14.521,14.376V18.376L20.9,12L14.521,5.621ZM13.384,2.584C13.576,2.608 13.751,2.704 13.874,2.854L22.667,11.646C22.714,11.692 22.75,11.748 22.776,11.808C22.801,11.869 22.814,11.934 22.814,12C22.814,12.066 22.801,12.131 22.776,12.192C22.75,12.252 22.714,12.307 22.667,12.354L13.874,21.146C13.751,21.295 13.576,21.392 13.384,21.416C13.165,21.416 13.021,21.199 13.021,20.793V16C10.922,16.074 8.863,16.596 6.983,17.532C5.103,18.468 3.445,19.796 2.121,21.426C1.839,21.781 1.607,21.955 1.444,21.955C1.23,21.955 1.139,21.655 1.222,21.055C2.2,14.051 5.757,8.934 13.021,8V3.207C13.021,2.801 13.165,2.584 13.384,2.584V2.584Z"
android:fillColor="@color/core_white"/>
</vector>

Wyświetl plik

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8.75,5.433C8.417,5.241 8.417,4.759 8.75,4.567L13.25,1.969C13.583,1.776 14,2.017 14,2.402V4.2C18.565,5.127 22,9.162 22,14C22,19.523 17.523,24 12,24C6.477,24 2,19.523 2,14C2,11.037 3.289,8.374 5.337,6.543L6.4,7.606C4.622,9.164 3.5,11.451 3.5,14C3.5,18.694 7.306,22.5 12,22.5C16.694,22.5 20.5,18.694 20.5,14C20.5,9.994 17.729,6.636 14,5.737V7.598C14,7.983 13.583,8.223 13.25,8.031L8.75,5.433Z"
android:fillColor="@color/core_white"/>
<path
android:pathData="M10.398,11.084V17.5H9.234V12.442L7.691,12.952V12.011L10.266,11.084H10.398Z"
android:fillColor="@color/core_white"/>
<path
android:pathData="M13.523,14.556L12.595,14.332L12.951,11.102H16.472V12.064H13.914L13.747,13.558C13.838,13.502 13.97,13.447 14.142,13.391C14.318,13.333 14.516,13.303 14.736,13.303C15.04,13.303 15.313,13.353 15.553,13.453C15.793,13.549 15.997,13.69 16.164,13.875C16.334,14.059 16.461,14.285 16.546,14.551C16.634,14.815 16.678,15.114 16.678,15.448C16.678,15.741 16.634,16.016 16.546,16.274C16.461,16.529 16.331,16.756 16.155,16.955C15.979,17.151 15.758,17.307 15.491,17.421C15.225,17.532 14.911,17.588 14.551,17.588C14.279,17.588 14.016,17.548 13.764,17.469C13.516,17.387 13.291,17.269 13.092,17.113C12.893,16.955 12.733,16.762 12.613,16.533C12.496,16.305 12.432,16.042 12.42,15.747H13.567C13.587,15.943 13.64,16.11 13.725,16.248C13.81,16.385 13.921,16.491 14.059,16.564C14.2,16.637 14.362,16.674 14.547,16.674C14.714,16.674 14.857,16.643 14.977,16.581C15.1,16.517 15.201,16.428 15.281,16.313C15.36,16.199 15.418,16.065 15.456,15.909C15.495,15.754 15.514,15.584 15.514,15.399C15.514,15.221 15.491,15.058 15.448,14.912C15.404,14.762 15.336,14.633 15.245,14.525C15.155,14.417 15.04,14.333 14.903,14.274C14.768,14.216 14.61,14.186 14.428,14.186C14.185,14.186 13.997,14.223 13.866,14.296C13.737,14.37 13.622,14.456 13.523,14.556Z"
android:fillColor="@color/core_white"/>
</vector>

Wyświetl plik

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M15.25,5.433C15.583,5.241 15.583,4.759 15.25,4.567L10.75,1.969C10.417,1.776 10,2.017 10,2.402V4.2C5.436,5.127 2,9.162 2,14C2,19.523 6.477,24 12,24C17.523,24 22,19.523 22,14C22,11.037 20.711,8.374 18.663,6.543L17.6,7.606C19.378,9.164 20.5,11.451 20.5,14C20.5,18.694 16.694,22.5 12,22.5C7.306,22.5 3.5,18.694 3.5,14C3.5,9.994 6.271,6.636 10,5.737V7.598C10,7.983 10.417,8.223 10.75,8.031L15.25,5.433Z"
android:fillColor="@color/core_white"/>
<path
android:pathData="M10.398,11.084V17.5H9.234V12.442L7.691,12.952V12.011L10.266,11.084H10.398Z"
android:fillColor="@color/core_white"/>
<path
android:pathData="M13.523,14.556L12.595,14.332L12.951,11.102H16.472V12.064H13.914L13.747,13.558C13.838,13.502 13.97,13.447 14.142,13.391C14.318,13.333 14.516,13.303 14.736,13.303C15.04,13.303 15.313,13.353 15.553,13.453C15.793,13.549 15.997,13.69 16.164,13.875C16.334,14.059 16.461,14.285 16.546,14.551C16.634,14.815 16.678,15.114 16.678,15.448C16.678,15.741 16.634,16.016 16.546,16.274C16.461,16.529 16.331,16.756 16.155,16.955C15.979,17.151 15.758,17.307 15.491,17.421C15.225,17.532 14.911,17.588 14.551,17.588C14.279,17.588 14.016,17.548 13.764,17.469C13.516,17.387 13.291,17.269 13.092,17.113C12.893,16.955 12.733,16.762 12.613,16.533C12.496,16.305 12.432,16.042 12.42,15.747H13.567C13.587,15.943 13.64,16.11 13.725,16.248C13.81,16.385 13.921,16.491 14.059,16.564C14.2,16.637 14.362,16.674 14.547,16.674C14.714,16.674 14.857,16.643 14.977,16.581C15.1,16.517 15.201,16.428 15.281,16.313C15.36,16.199 15.418,16.065 15.456,15.909C15.495,15.754 15.514,15.584 15.514,15.399C15.514,15.221 15.491,15.058 15.448,14.912C15.404,14.762 15.336,14.633 15.245,14.525C15.155,14.417 15.04,14.333 14.903,14.274C14.768,14.216 14.61,14.186 14.428,14.186C14.185,14.186 13.997,14.223 13.866,14.296C13.737,14.37 13.622,14.456 13.523,14.556Z"
android:fillColor="@color/core_white"/>
</vector>

Wyświetl plik

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22,4.5H16.35C16.136,3.506 15.587,2.615 14.795,1.976C14.004,1.337 13.017,0.988 12,0.988C10.983,0.988 9.996,1.337 9.205,1.976C8.413,2.615 7.864,3.506 7.65,4.5H2V6H3.5L4.86,20C4.922,20.551 5.184,21.059 5.598,21.428C6.011,21.797 6.546,22.001 7.1,22H16.9C17.454,22.001 17.989,21.797 18.403,21.428C18.816,21.059 19.078,20.551 19.14,20L20.5,6H22V4.5ZM12,2.5C12.619,2.502 13.222,2.695 13.727,3.053C14.232,3.411 14.614,3.916 14.82,4.5H9.18C9.386,3.916 9.768,3.411 10.273,3.053C10.778,2.695 11.381,2.502 12,2.5V2.5ZM17.65,19.83C17.628,20.014 17.54,20.183 17.402,20.307C17.264,20.43 17.085,20.499 16.9,20.5H7.1C6.915,20.499 6.736,20.43 6.598,20.307C6.46,20.183 6.372,20.014 6.35,19.83L5,6H19L17.65,19.83ZM11.25,18V8H12.75V18H11.25ZM14.5,18L15,8H16.5L16,18H14.5ZM8,18L7.5,8H9L9.5,18H8Z"
android:fillColor="#000000"/>
</vector>

Wyświetl plik

@ -5,51 +5,69 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:background="#CC000000" android:background="@color/transparent"
android:layoutDirection="ltr" android:layoutDirection="ltr"
android:orientation="vertical" android:orientation="vertical"
tools:targetApi="28"> tools:targetApi="28">
<LinearLayout <LinearLayout
android:id="@+id/exo_duration_viewgroup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginStart="@dimen/media_preview_video_timestamp_inset"
android:layout_marginTop="@dimen/media_preview_bottom_bar_vertical_margin"
android:layout_marginEnd="@dimen/media_preview_video_timestamp_inset"
android:layout_marginBottom="@dimen/media_preview_bottom_bar_vertical_margin"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@id/exo_position" android:id="@id/exo_position"
style="@style/Signal.Text.BodyMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:includeFontPadding="false" android:includeFontPadding="false"
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:textColor="#FFBEBEBE" android:textColor="#FFBEBEBE"
android:textSize="14sp" android:textSize="14sp" />
android:textStyle="bold" />
<View <com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress_placeholder" android:id="@id/exo_progress"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="26dp" android:layout_height="26dp"
android:layout_weight="1" /> android:layout_weight="1" />
<TextView <TextView
android:id="@id/exo_duration" android:id="@id/exo_duration"
style="@style/Signal.Text.BodyMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:includeFontPadding="false" android:includeFontPadding="false"
android:paddingLeft="4dp" android:paddingLeft="4dp"
android:paddingRight="4dp" android:paddingRight="4dp"
android:textColor="#FFBEBEBE" android:textColor="#FFBEBEBE"
android:textSize="14sp" android:textSize="14sp" />
android:textStyle="bold" />
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/media_preview_album_rail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="12dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:layout_height="64dp" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/media_preview_bottom_bar_vertical_margin"
android:layout_marginBottom="@dimen/media_preview_bottom_bar_vertical_margin"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingTop="4dp"> android:paddingTop="4dp">
@ -66,13 +84,22 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1.0" /> android:layout_weight="1.0" />
<LinearLayout
android:id="@+id/exo_button_viewgroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<ImageButton <ImageButton
android:id="@id/exo_prev" android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous" /> style="@style/ExoMediaButton.Previous" />
<ImageButton <ImageButton
android:id="@id/exo_rew" android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind" /> style="@style/ExoMediaButton"
android:contentDescription="@string/exo_controls_rewind_description"
app:srcCompat="@drawable/ic_media_skipback_outline_24" />
<ImageButton <ImageButton
android:id="@id/exo_shuffle" android:id="@id/exo_shuffle"
@ -92,7 +119,9 @@
<ImageButton <ImageButton
android:id="@id/exo_ffwd" android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward" /> style="@style/ExoMediaButton"
android:contentDescription="@string/exo_controls_fastforward_description"
app:srcCompat="@drawable/ic_media_skipforward_outline_24" />
<ImageButton <ImageButton
android:id="@id/exo_next" android:id="@id/exo_next"
@ -101,6 +130,7 @@
<ImageButton <ImageButton
android:id="@id/exo_vr" android:id="@id/exo_vr"
style="@style/ExoMediaButton.VR" /> style="@style/ExoMediaButton.VR" />
</LinearLayout>
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@ -112,7 +142,7 @@
android:layout_width="@dimen/exo_media_button_width" android:layout_width="@dimen/exo_media_button_width"
android:layout_height="@dimen/exo_media_button_height" android:layout_height="@dimen/exo_media_button_height"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
app:srcCompat="@drawable/ic_forward_24" /> app:srcCompat="@drawable/ic_forward_outline_24" />
</LinearLayout> </LinearLayout>

Wyświetl plik

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools" android:background="@color/signal_dark_colorSurface">
android:background="@color/signal_dark_colorNeutral">
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/media_pager" android:id="@+id/media_pager"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -18,45 +19,37 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:background="@drawable/image_preview_shade" android:background="@color/signal_dark_colorSurface_87"
android:gravity="bottom" android:gravity="bottom"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible"> tools:visibility="visible">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView <org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/media_preview_caption" android:id="@+id/media_preview_caption"
style="@style/Signal.Text.Body"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="16dp" android:paddingEnd="16dp"
android:paddingBottom="8dp" android:paddingBottom="8dp"
style="@style/Signal.Text.Body"
android:textColor="@color/core_white" android:textColor="@color/core_white"
android:gravity="bottom"
tools:text="With great power comes great responsibility." /> tools:text="With great power comes great responsibility." />
<androidx.recyclerview.widget.RecyclerView <org.thoughtcrime.securesms.mediapreview.MediaPreviewPlayerControlView
android:id="@+id/media_preview_album_rail" android:id="@+id/media_preview_playback_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:animateLayoutChanges="true"
android:layout_marginStart="12dp" android:background="@color/transparent" />
android:layout_marginEnd="12dp"
tools:layout_height="64dp"/>
<FrameLayout
android:id="@+id/media_preview_playback_controls_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"/>
</LinearLayout> </LinearLayout>
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_layout" android:id="@+id/toolbar_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/media_preview_bar_background" android:background="@color/signal_dark_colorSurface_87"
app:elevation="0dp"> app:elevation="0dp">
<View <View
@ -67,10 +60,10 @@
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:theme="?actionBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:theme="?actionBarStyle"
app:navigationIcon="@drawable/ic_arrow_left_white_24" /> app:navigationIcon="@drawable/ic_arrow_left_white_24" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>

Wyświetl plik

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_gravity="bottom"
android:background="#CC000000"
android:layoutDirection="ltr"
android:orientation="vertical"
tools:targetApi="28">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
android:id="@+id/image_preview_share"
android:layout_width="@dimen/exo_media_button_width"
android:layout_height="@dimen/exo_media_button_height"
android:background="?selectableItemBackground"
app:srcCompat="@drawable/ic_share_24_outline_white" />
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1.0" />
<ImageButton
android:id="@+id/image_preview_forward"
android:layout_width="@dimen/exo_media_button_width"
android:layout_height="@dimen/exo_media_button_height"
android:background="?selectableItemBackground"
app:srcCompat="@drawable/ic_forward_24" />
</LinearLayout>
</LinearLayout>

Wyświetl plik

@ -235,4 +235,6 @@
<dimen name="stories_landing_item_thumb_outline_width">52dp</dimen> <dimen name="stories_landing_item_thumb_outline_width">52dp</dimen>
<dimen name="stories_landing_item_thumb_outline_height">76dp</dimen> <dimen name="stories_landing_item_thumb_outline_height">76dp</dimen>
<dimen name="stories_landing_item_text_horizontal_margin">20dp</dimen> <dimen name="stories_landing_item_text_horizontal_margin">20dp</dimen>
<dimen name="media_preview_video_timestamp_inset">24dp</dimen>
<dimen name="media_preview_bottom_bar_vertical_margin">20dp</dimen>
</resources> </resources>

Wyświetl plik

@ -43,5 +43,6 @@
<color name="signal_dark_colorNeutralVariantInverse">#A3FFFFFF</color> <color name="signal_dark_colorNeutralVariantInverse">#A3FFFFFF</color>
<color name="signal_dark_colorBackground_92">#EB1B1C1F</color> <color name="signal_dark_colorBackground_92">#EB1B1C1F</color>
<color name="signal_dark_colorSurface_87">#DE1B1C1F</color>
<color name="signal_dark_colorSurfaceVariant_92">#EB303133</color> <color name="signal_dark_colorSurfaceVariant_92">#EB303133</color>
</resources> </resources>