Procházet zdrojové kódy

Video preview: use fullscreen dialog for video instead of new activity

This allows transfering the playback directly between Player views, thus avoiding creating
a new ExoPlayer, re-starting the stream, having to pass playing status/current position, etc.

Additionally:
- Always enable buffering animation so it's clear when a video is loading
- Add padding to fullscreen duration numbers so they don't get cut off on rounded screens

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey před 2 roky
rodič
revize
bbb85513e1

+ 0 - 4
app/src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -124,7 +124,6 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewTextFileFragment;
 import com.owncloud.android.ui.preview.PreviewTextFileFragment;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
 import com.owncloud.android.ui.preview.PreviewTextStringFragment;
 import com.owncloud.android.ui.preview.PreviewTextStringFragment;
-import com.owncloud.android.ui.preview.PreviewVideoActivity;
 import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.ui.trashbin.TrashbinActivity;
 import com.owncloud.android.ui.trashbin.TrashbinActivity;
 import com.owncloud.android.utils.FilesUploadHelper;
 import com.owncloud.android.utils.FilesUploadHelper;
@@ -200,9 +199,6 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector
     @ContributesAndroidInjector
     abstract PreviewImageActivity previewImageActivity();
     abstract PreviewImageActivity previewImageActivity();
 
 
-    @ContributesAndroidInjector
-    abstract PreviewVideoActivity previewVideoActivity();
-
     @ContributesAndroidInjector
     @ContributesAndroidInjector
     abstract ReceiveExternalFilesActivity receiveExternalFilesActivity();
     abstract ReceiveExternalFilesActivity receiveExternalFilesActivity();
 
 

+ 5 - 6
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -118,7 +118,6 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewTextFileFragment;
 import com.owncloud.android.ui.preview.PreviewTextFileFragment;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
 import com.owncloud.android.ui.preview.PreviewTextStringFragment;
 import com.owncloud.android.ui.preview.PreviewTextStringFragment;
-import com.owncloud.android.ui.preview.PreviewVideoActivity;
 import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.ui.preview.pdf.PreviewPdfFragment;
 import com.owncloud.android.utils.DataHolderUtil;
 import com.owncloud.android.utils.DataHolderUtil;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.DisplayUtils;
@@ -2191,8 +2190,8 @@ public class FileDisplayActivity extends FileActivity
         } else {
         } else {
             Intent previewIntent = new Intent();
             Intent previewIntent = new Intent();
             previewIntent.putExtra(EXTRA_FILE, file);
             previewIntent.putExtra(EXTRA_FILE, file);
-            previewIntent.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, startPlaybackPosition);
-            previewIntent.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, autoplay);
+            previewIntent.putExtra(PreviewMediaFragment.EXTRA_START_POSITION, startPlaybackPosition);
+            previewIntent.putExtra(PreviewMediaFragment.EXTRA_AUTOPLAY, autoplay);
             FileOperationsHelper fileOperationsHelper = new FileOperationsHelper(this,
             FileOperationsHelper fileOperationsHelper = new FileOperationsHelper(this,
                                                                                  getUserAccountManager(),
                                                                                  getUserAccountManager(),
                                                                                  connectivityService, editorUtils);
                                                                                  connectivityService, editorUtils);
@@ -2373,10 +2372,10 @@ public class FileDisplayActivity extends FileActivity
         Bundle bundle = event.getIntent().getExtras();
         Bundle bundle = event.getIntent().getExtras();
         if (event.getIntent().getBooleanExtra(TEXT_PREVIEW, false)) {
         if (event.getIntent().getBooleanExtra(TEXT_PREVIEW, false)) {
             startTextPreview((OCFile) bundle.get(EXTRA_FILE), true);
             startTextPreview((OCFile) bundle.get(EXTRA_FILE), true);
-        } else if (bundle.containsKey(PreviewVideoActivity.EXTRA_START_POSITION)) {
+        } else if (bundle.containsKey(PreviewMediaFragment.EXTRA_START_POSITION)) {
             startMediaPreview((OCFile) bundle.get(EXTRA_FILE),
             startMediaPreview((OCFile) bundle.get(EXTRA_FILE),
-                              (long) bundle.get(PreviewVideoActivity.EXTRA_START_POSITION),
-                              (boolean) bundle.get(PreviewVideoActivity.EXTRA_AUTOPLAY), true, true);
+                              (long) bundle.get(PreviewMediaFragment.EXTRA_START_POSITION),
+                              (boolean) bundle.get(PreviewMediaFragment.EXTRA_AUTOPLAY), true, true);
         } else if (bundle.containsKey(PreviewImageActivity.EXTRA_VIRTUAL_TYPE)) {
         } else if (bundle.containsKey(PreviewImageActivity.EXTRA_VIRTUAL_TYPE)) {
             startImagePreview((OCFile) bundle.get(EXTRA_FILE),
             startImagePreview((OCFile) bundle.get(EXTRA_FILE),
                               (VirtualFolderType) bundle.get(PreviewImageActivity.EXTRA_VIRTUAL_TYPE),
                               (VirtualFolderType) bundle.get(PreviewImageActivity.EXTRA_VIRTUAL_TYPE),

+ 7 - 11
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -68,7 +68,6 @@ import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.activity.DrawerActivity;
 import com.owncloud.android.ui.activity.DrawerActivity;
-import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
 import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
@@ -105,10 +104,14 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
 
 
     public static final String EXTRA_FILE = "FILE";
     public static final String EXTRA_FILE = "FILE";
     public static final String EXTRA_USER = "USER";
     public static final String EXTRA_USER = "USER";
+    public static final String EXTRA_AUTOPLAY = "AUTOPLAY";
+    public static final String EXTRA_START_POSITION = "START_POSITION";
+    
     private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
     private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
     private static final String EXTRA_PLAYING = "PLAYING";
     private static final String EXTRA_PLAYING = "PLAYING";
     private static final double MIN_DENSITY_RATIO = 24.0;
     private static final double MIN_DENSITY_RATIO = 24.0;
 
 
+
     private static final String FILE = "FILE";
     private static final String FILE = "FILE";
     private static final String USER = "USER";
     private static final String USER = "USER";
     private static final String PLAYBACK_POSITION = "PLAYBACK_POSITION";
     private static final String PLAYBACK_POSITION = "PLAYBACK_POSITION";
@@ -602,14 +605,7 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
     }
     }
 
 
     private void startFullScreenVideo() {
     private void startFullScreenVideo() {
-        Intent intent = new Intent(getActivity(), PreviewVideoActivity.class);
-        intent.putExtra(FileActivity.EXTRA_USER, user);
-        intent.putExtra(FileActivity.EXTRA_FILE, getFile());
-        intent.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, exoPlayer.isPlaying());
-        intent.putExtra(PreviewVideoActivity.EXTRA_STREAM_URL, videoUri);
-        exoPlayer.pause();
-        intent.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, exoPlayer.getCurrentPosition());
-        startActivityForResult(intent, FileActivity.REQUEST_CODE__LAST_SHARED + 1);
+        new PreviewVideoFullscreenDialog(getActivity(), exoPlayer, binding.exoplayerView).show();
     }
     }
 
 
     @Override
     @Override
@@ -623,8 +619,8 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
         Log_OC.v(TAG, "onActivityResult " + this);
         Log_OC.v(TAG, "onActivityResult " + this);
         super.onActivityResult(requestCode, resultCode, data);
         super.onActivityResult(requestCode, resultCode, data);
         if (resultCode == Activity.RESULT_OK) {
         if (resultCode == Activity.RESULT_OK) {
-            savedPlaybackPosition = data.getLongExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
-            autoplay = data.getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, false);
+            savedPlaybackPosition = data.getLongExtra(PreviewMediaFragment.EXTRA_START_POSITION, 0);
+            autoplay = data.getBooleanExtra(PreviewMediaFragment.EXTRA_AUTOPLAY, false);
         }
         }
     }
     }
 
 

+ 0 - 211
app/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.kt

@@ -1,211 +0,0 @@
-/*
- *   ownCloud Android client application
- *
- *   @author David A. Velasco
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-package com.owncloud.android.ui.preview
-
-import android.content.Intent
-import android.net.Uri
-import android.os.Bundle
-import android.view.View
-import com.google.android.exoplayer2.ExoPlayer
-import com.google.android.exoplayer2.MediaItem
-import com.google.android.exoplayer2.Player
-import com.nextcloud.client.account.UserAccountManager
-import com.nextcloud.client.di.Injectable
-import com.nextcloud.client.media.ExoplayerListener
-import com.nextcloud.client.media.NextcloudExoPlayer.createNextcloudExoplayer
-import com.nextcloud.client.network.ClientFactory
-import com.owncloud.android.R
-import com.owncloud.android.databinding.ActivityPreviewVideoBinding
-import com.owncloud.android.datamodel.OCFile
-import com.owncloud.android.lib.common.utils.Log_OC
-import com.owncloud.android.ui.activity.FileActivity
-import com.owncloud.android.utils.MimeTypeUtil
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-/**
- * Activity implementing a basic video player.
- *
- */
-@Suppress("TooManyFunctions")
-class PreviewVideoActivity :
-    FileActivity(),
-    Player.Listener,
-    Injectable {
-
-    @Inject
-    lateinit var clientFactory: ClientFactory
-
-    @Inject
-    lateinit var accountManager: UserAccountManager
-
-    private var mSavedPlaybackPosition: Long = -1 // in the unit time handled by MediaPlayer.getCurrentPosition()
-    private var mAutoplay = false // when 'true', the playback starts immediately with the activity
-    private var exoPlayer: ExoPlayer? = null // view to play the file; both performs and show the playback
-    private var mStreamUri: Uri? = null
-    private lateinit var binding: ActivityPreviewVideoBinding
-
-    private lateinit var pauseButton: View
-
-    private lateinit var playButton: View
-
-    public override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        Log_OC.v(TAG, "onCreate")
-
-        binding = ActivityPreviewVideoBinding.inflate(layoutInflater)
-        setContentView(binding.root)
-
-        val extras = intent.extras
-
-        if (savedInstanceState == null && extras != null) {
-            mSavedPlaybackPosition = extras.getLong(EXTRA_START_POSITION)
-            mAutoplay = extras.getBoolean(EXTRA_AUTOPLAY)
-            mStreamUri = extras[EXTRA_STREAM_URL] as Uri?
-        } else if (savedInstanceState != null) {
-            mSavedPlaybackPosition = savedInstanceState.getLong(EXTRA_START_POSITION)
-            mAutoplay = savedInstanceState.getBoolean(EXTRA_AUTOPLAY)
-            mStreamUri = savedInstanceState[EXTRA_STREAM_URL] as Uri?
-        }
-
-        supportActionBar?.hide()
-    }
-
-    private fun setupPlayerView() {
-        binding.videoPlayer.player = exoPlayer
-        exoPlayer!!.addListener(this)
-
-        binding.root.findViewById<View>(R.id.exo_exit_fs).setOnClickListener { onBackPressed() }
-
-        pauseButton = binding.root.findViewById(R.id.exo_pause)
-        pauseButton.setOnClickListener { exoPlayer!!.pause() }
-
-        playButton = binding.root.findViewById(R.id.exo_play)
-        playButton.setOnClickListener { exoPlayer!!.play() }
-
-        if (mSavedPlaybackPosition >= 0) {
-            exoPlayer?.seekTo(mSavedPlaybackPosition)
-        }
-
-        onIsPlayingChanged(exoPlayer!!.isPlaying)
-    }
-
-    override fun onIsPlayingChanged(isPlaying: Boolean) {
-        super.onIsPlayingChanged(isPlaying)
-        if (isPlaying) {
-            playButton.visibility = View.GONE
-            pauseButton.visibility = View.VISIBLE
-        } else {
-            playButton.visibility = View.VISIBLE
-            pauseButton.visibility = View.GONE
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public override fun onSaveInstanceState(outState: Bundle) {
-        super.onSaveInstanceState(outState)
-        outState.putLong(EXTRA_START_POSITION, currentPosition())
-        outState.putBoolean(EXTRA_AUTOPLAY, isPlaying())
-        outState.putParcelable(EXTRA_STREAM_URL, mStreamUri)
-    }
-
-    override fun onBackPressed() {
-        Log_OC.v(TAG, "onBackPressed")
-        val i = Intent()
-        i.putExtra(EXTRA_AUTOPLAY, isPlaying())
-        i.putExtra(EXTRA_START_POSITION, currentPosition())
-        setResult(RESULT_OK, i)
-        exoPlayer?.stop()
-        exoPlayer?.release()
-        super.onBackPressed()
-    }
-
-    private fun isPlaying() = exoPlayer?.isPlaying ?: false
-    private fun currentPosition() = exoPlayer?.currentPosition ?: 0
-
-    private fun play(item: MediaItem) {
-        exoPlayer?.addMediaItem(item)
-        exoPlayer?.prepare()
-
-        if (mAutoplay) {
-            exoPlayer?.play()
-        }
-    }
-
-    override fun onStart() {
-        super.onStart()
-        if (account != null) {
-            require(file != null) { throw IllegalStateException("Instanced with a NULL OCFile") }
-            var fileToPlay: OCFile? = file
-
-            // Validate handled file  (first image to preview)
-            require(MimeTypeUtil.isVideo(fileToPlay)) { "Non-video file passed as argument" }
-
-            fileToPlay = storageManager.getFileById(fileToPlay!!.fileId)
-            if (fileToPlay != null) {
-                val mediaItem = when {
-                    fileToPlay.isDown -> MediaItem.fromUri(fileToPlay.storageUri)
-                    else -> MediaItem.fromUri(mStreamUri!!)
-                }
-                if (exoPlayer != null) {
-                    setupPlayerView()
-                    play(mediaItem)
-                } else {
-                    val context = this
-                    CoroutineScope(Dispatchers.IO).launch {
-                        val client = clientFactory.createNextcloudClient(accountManager.user)
-                        CoroutineScope(Dispatchers.Main).launch {
-                            exoPlayer = createNextcloudExoplayer(context, client).also {
-                                it.addListener(ExoplayerListener(context, binding.videoPlayer, it))
-                            }
-                            setupPlayerView()
-                            play(mediaItem)
-                        }
-                    }
-                }
-            } else {
-                finish()
-            }
-        } else {
-            finish()
-        }
-    }
-
-    override fun onStop() {
-        super.onStop()
-        if (exoPlayer?.isPlaying == true) {
-            exoPlayer?.pause()
-        }
-    }
-
-    companion object {
-        /** Key to receive a flag signaling if the video should be started immediately  */
-        const val EXTRA_AUTOPLAY = "AUTOPLAY"
-
-        /** Key to receive the position of the playback where the video should be put at start  */
-        const val EXTRA_START_POSITION = "START_POSITION"
-        const val EXTRA_STREAM_URL = "STREAM_URL"
-        private val TAG = PreviewVideoActivity::class.java.simpleName
-    }
-}

+ 134 - 0
app/src/main/java/com/owncloud/android/ui/preview/PreviewVideoFullscreenDialog.kt

@@ -0,0 +1,134 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.preview
+
+import android.app.Activity
+import android.app.Dialog
+import android.view.View
+import android.view.ViewGroup
+import android.view.Window
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
+import com.google.android.exoplayer2.ExoPlayer
+import com.google.android.exoplayer2.Player
+import com.google.android.exoplayer2.ui.StyledPlayerView
+import com.owncloud.android.R
+import com.owncloud.android.databinding.DialogPreviewVideoBinding
+
+/**
+ * Transfers a previously playing video to a fullscreen dialog, and handles the switch back to the previous player
+ * when closed
+ *
+ * @param activity the Activity hosting the original non-fullscreen player
+ * @param exoPlayer the ExoPlayer playing the video
+ * @param sourceView the original non-fullscreen surface that [exoPlayer] is linked to
+ */
+class PreviewVideoFullscreenDialog(
+    private val activity: Activity,
+    private val exoPlayer: ExoPlayer,
+    private val sourceView: StyledPlayerView
+) : Dialog(sourceView.context, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
+
+    private val binding: DialogPreviewVideoBinding = DialogPreviewVideoBinding.inflate(layoutInflater)
+    private var playingStateListener: Player.Listener? = null
+
+    init {
+        addContentView(
+            binding.root,
+            ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
+        )
+    }
+
+    override fun show() {
+        goFullScreen()
+        super.show()
+        binding.videoPlayer.showController()
+    }
+
+    private fun goFullScreen() {
+        setListeners(exoPlayer)
+        StyledPlayerView.switchTargetView(exoPlayer, sourceView, binding.videoPlayer)
+        enableImmersiveMode()
+    }
+
+    private fun setListeners(exoPlayer: ExoPlayer) {
+        binding.root.findViewById<View>(R.id.exo_exit_fs).setOnClickListener { onBackPressed() }
+        val pauseButton: View = binding.root.findViewById(R.id.exo_pause)
+        pauseButton.setOnClickListener { exoPlayer.pause() }
+        val playButton: View = binding.root.findViewById(R.id.exo_play)
+        playButton.setOnClickListener { exoPlayer.play() }
+
+        val playListener = object : Player.Listener {
+            override fun onIsPlayingChanged(isPlaying: Boolean) {
+                super.onIsPlayingChanged(isPlaying)
+                if (isPlaying) {
+                    playButton.visibility = View.GONE
+                    pauseButton.visibility = View.VISIBLE
+                } else {
+                    playButton.visibility = View.VISIBLE
+                    pauseButton.visibility = View.GONE
+                }
+            }
+        }
+        exoPlayer.addListener(playListener)
+        playingStateListener = playListener
+    }
+
+    override fun onBackPressed() {
+        playingStateListener?.let {
+            exoPlayer.removeListener(it)
+        }
+        StyledPlayerView.switchTargetView(exoPlayer, binding.videoPlayer, sourceView)
+        disableImmersiveMode()
+        super.onBackPressed()
+        sourceView.showController()
+    }
+
+    private fun enableImmersiveMode() {
+        // for immersive mode to work properly, need to disable statusbar on activity window, but nav bar in dialog
+        // otherwise dialog navbar is not hidden, or statusbar padding is the wrong color
+        activity.window?.let {
+            hideInset(it, WindowInsetsCompat.Type.statusBars())
+        }
+        window?.let {
+            hideInset(it, WindowInsetsCompat.Type.systemBars())
+        }
+    }
+
+    private fun hideInset(window: Window, type: Int) {
+        val windowInsetsController =
+            WindowCompat.getInsetsController(window, window.decorView)
+        windowInsetsController.systemBarsBehavior =
+            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+        windowInsetsController.hide(type)
+    }
+
+    private fun disableImmersiveMode() {
+        activity.window?.let {
+            val windowInsetsController =
+                WindowCompat.getInsetsController(it, it.decorView)
+            windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
+        } ?: return
+    }
+}

+ 1 - 0
app/src/main/res/layout/activity_preview_video.xml → app/src/main/res/layout/dialog_preview_video.xml

@@ -25,4 +25,5 @@
     android:layout_height="match_parent"
     android:layout_height="match_parent"
     android:layout_gravity="center"
     android:layout_gravity="center"
     android:background="@color/black"
     android:background="@color/black"
+    app:show_buffering="always"
     app:controller_layout_id="@layout/exo_player_control_view" />
     app:controller_layout_id="@layout/exo_player_control_view" />

+ 4 - 4
app/src/main/res/layout/exo_player_control_view.xml

@@ -83,8 +83,8 @@
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textSize="14sp"
             android:textSize="14sp"
             android:textStyle="bold"
             android:textStyle="bold"
-            android:paddingLeft="4dp"
-            android:paddingRight="4dp"
+            android:layout_marginStart="@dimen/standard_margin"
+            android:paddingHorizontal="4dp"
             android:includeFontPadding="false"
             android:includeFontPadding="false"
             android:textColor="#FFBEBEBE" />
             android:textColor="#FFBEBEBE" />
 
 
@@ -100,8 +100,8 @@
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
             android:textSize="14sp"
             android:textSize="14sp"
             android:textStyle="bold"
             android:textStyle="bold"
-            android:paddingLeft="4dp"
-            android:paddingRight="4dp"
+            android:layout_marginEnd="@dimen/standard_margin"
+            android:paddingHorizontal="4dp"
             android:includeFontPadding="false"
             android:includeFontPadding="false"
             android:textColor="#FFBEBEBE" />
             android:textColor="#FFBEBEBE" />
 
 

+ 1 - 1
app/src/main/res/layout/fragment_preview_media.xml

@@ -43,7 +43,7 @@
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_height="match_parent"
         android:layout_gravity="center"
         android:layout_gravity="center"
-        app:show_buffering="when_playing"
+        app:show_buffering="always"
         app:show_next_button="false" />
         app:show_next_button="false" />
 
 
     <com.owncloud.android.media.MediaControlView
     <com.owncloud.android.media.MediaControlView