Browse Source

Merge pull request #12952 from nextcloud/bugfix/media-control-view-visibility

Fix Media Control View Visibility
Alper Öztürk 1 năm trước cách đây
mục cha
commit
361f9ddbb2

+ 0 - 343
app/src/main/java/com/owncloud/android/media/MediaControlView.java

@@ -1,343 +0,0 @@
-/*
- * Nextcloud - Android Client
- *
- * SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
- * SPDX-FileCopyrightText: 2022 Álvaro Brey Vilas <alvaro@alvarobrey.com>
- * SPDX-FileCopyrightText: 2018-2020 Tobias Kaminsky <tobias@kaminsky.me>
- * SPDX-FileCopyrightText: 2019 Chris Narkiewicz <hello@ezaquarii.com>
- * SPDX-FileCopyrightText: 2018 Andy Scherzinger <info@andy-scherzinger.de>
- * SPDX-FileCopyrightText: 2015 ownCloud Inc.
- * SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
- * SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
- */
-package com.owncloud.android.media;
-
-import android.content.Context;
-import android.media.MediaPlayer;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.LinearLayout;
-import android.widget.MediaController.MediaPlayerControl;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-import com.owncloud.android.MainApp;
-import com.owncloud.android.R;
-import com.owncloud.android.databinding.MediaControlBinding;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import java.util.Formatter;
-import java.util.Locale;
-
-import javax.inject.Inject;
-
-/**
- * View containing controls for a {@link MediaPlayer}.
- * <p>
- * Holds buttons "play / pause", "rewind", "fast forward" and a progress slider.
- * <p>
- * It synchronizes itself with the state of the {@link MediaPlayer}.
- */
-public class MediaControlView extends LinearLayout implements OnClickListener, OnSeekBarChangeListener {
-    private static final String TAG = MediaControlView.class.getSimpleName();
-    private static final int SHOW_PROGRESS = 1;
-
-    private MediaPlayerControl playerControl;
-    private final MediaControlBinding binding;
-    private boolean isDragging;
-
-    @Inject
-    ViewThemeUtils viewThemeUtils;
-
-    public MediaControlView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        MainApp.getAppComponent().inject(this);
-
-        LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        binding = MediaControlBinding.inflate(inflate, this, true);
-        initControllerView();
-
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
-        requestFocus();
-    }
-
-    @Override
-    public void onFinishInflate() {
-        super.onFinishInflate();
-    }
-
-    public void setMediaPlayer(MediaPlayerControl player) {
-        playerControl = player;
-        handler.sendEmptyMessage(SHOW_PROGRESS);
-        handler.postDelayed(() -> {
-            updatePausePlay();
-            setProgress();
-        }, 100);
-    }
-
-    public void stopMediaPlayerMessages() {
-        handler.removeMessages(SHOW_PROGRESS);
-    }
-
-    private void initControllerView() {
-        binding.playBtn.requestFocus();
-        binding.playBtn.setOnClickListener(this);
-
-        binding.forwardBtn.setOnClickListener(this);
-
-        binding.rewindBtn.setOnClickListener(this);
-
-        viewThemeUtils.platform.themeHorizontalSeekBar(binding.progressBar);
-        binding.progressBar.setOnSeekBarChangeListener(this);
-        binding.progressBar.setMax(1000);
-    }
-
-    /**
-     * Disable pause or seek buttons if the stream cannot be paused or seeked.
-     * This requires the control interface to be a MediaPlayerControlExt
-     */
-    private void disableUnsupportedButtons() {
-        try {
-            if (binding != null) {
-                if (!playerControl.canPause()) {
-                    binding.playBtn.setEnabled(false);
-                }
-                if (!playerControl.canSeekBackward()) {
-                    binding.rewindBtn.setEnabled(false);
-                }
-                if (!playerControl.canSeekForward()) {
-                    binding.forwardBtn.setEnabled(false);
-                }
-            }
-
-        } catch (IncompatibleClassChangeError ex) {
-            // We were given an old version of the interface, that doesn't have
-            // the canPause/canSeekXYZ methods. This is OK, it just means we
-            // assume the media can be paused and seeked, and so we don't disable
-            // the buttons.
-            Log_OC.i(TAG, "Old media interface detected");
-        }
-    }
-
-    private final Handler handler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            if (msg.what == SHOW_PROGRESS) {
-                updatePausePlay();
-                int pos = setProgress();
-                if (!isDragging) {
-                    sendMessageDelayed(obtainMessage(SHOW_PROGRESS), 1000 - (pos % 1000));
-                }
-            }
-        }
-    };
-
-    private String formatTime(int timeMs) {
-        int totalSeconds = timeMs / 1000;
-
-        int seconds = totalSeconds % 60;
-        int minutes = (totalSeconds / 60) % 60;
-        int hours = totalSeconds / 3600;
-
-        final StringBuilder mFormatBuilder = new StringBuilder();
-        final Formatter mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
-        if (hours > 0) {
-            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
-        } else {
-            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
-        }
-    }
-
-    private int setProgress() {
-        if (playerControl == null || isDragging) {
-            return 0;
-        }
-        int position = playerControl.getCurrentPosition();
-        int duration = playerControl.getDuration();
-        if (binding != null) {
-            if (duration > 0) {
-                // use long to avoid overflow
-                long pos = 1000L * position / duration;
-                binding.progressBar.setProgress((int) pos);
-            }
-            int percent = playerControl.getBufferPercentage();
-            binding.progressBar.setSecondaryProgress(percent * 10);
-
-            String endTime = duration > 0 ? formatTime(duration) : "--:--";
-            binding.totalTimeText.setText(endTime);
-            binding.currentTimeText.setText(formatTime(position));
-        }
-
-        return position;
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        int keyCode = event.getKeyCode();
-        final boolean uniqueDown = event.getRepeatCount() == 0
-                && event.getAction() == KeyEvent.ACTION_DOWN;
-        if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
-                || keyCode == KeyEvent.KEYCODE_SPACE) {
-            if (uniqueDown) {
-                doPauseResume();
-                //show(sDefaultTimeout);
-                if (binding != null) {
-                    binding.playBtn.requestFocus();
-                }
-            }
-            return true;
-        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
-            if (uniqueDown && !playerControl.isPlaying()) {
-                playerControl.start();
-                updatePausePlay();
-            }
-            return true;
-        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
-                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
-            if (uniqueDown && playerControl.isPlaying()) {
-                playerControl.pause();
-                updatePausePlay();
-            }
-            return true;
-        }
-
-        return super.dispatchKeyEvent(event);
-    }
-
-    public void updatePausePlay() {
-        if (binding == null) {
-            return;
-        }
-
-        if (playerControl.isPlaying()) {
-            binding.playBtn.setImageResource(android.R.drawable.ic_media_pause);
-        } else {
-            binding.playBtn.setImageResource(android.R.drawable.ic_media_play);
-        }
-
-        final boolean canSeekFfd = playerControl.canSeekForward();
-        if (canSeekFfd) {
-            binding.forwardBtn.setVisibility(View.VISIBLE);
-        } else {
-            binding.forwardBtn.setVisibility(View.INVISIBLE);
-        }
-
-        final boolean canSeekBwd = playerControl.canSeekBackward();
-        if (canSeekBwd) {
-            binding.rewindBtn.setVisibility(View.VISIBLE);
-        } else {
-            binding.rewindBtn.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    private void doPauseResume() {
-        if (playerControl.isPlaying()) {
-            playerControl.pause();
-        } else {
-            playerControl.start();
-        }
-        updatePausePlay();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        if(binding!=null){
-            binding.playBtn.setEnabled(enabled);
-            binding.forwardBtn.setEnabled(enabled);
-            binding.rewindBtn.setEnabled(enabled);
-            binding.progressBar.setEnabled(enabled);
-        }
-
-        disableUnsupportedButtons();
-        super.setEnabled(enabled);
-    }
-
-    @Override
-    public void onClick(View v) {
-        int pos;
-        boolean playing = playerControl.isPlaying();
-        int id = v.getId();
-
-        if (id == R.id.playBtn) {
-            doPauseResume();
-        } else if (id == R.id.rewindBtn) {
-            pos = playerControl.getCurrentPosition();
-            pos -= 5000;
-            playerControl.seekTo(pos);
-            if (!playing) {
-                playerControl.pause();  // necessary in some 2.3.x devices
-            }
-            setProgress();
-        } else if (id == R.id.forwardBtn) {
-            pos = playerControl.getCurrentPosition();
-            pos += 15000;
-            playerControl.seekTo(pos);
-            if (!playing) {
-                playerControl.pause(); // necessary in some 2.3.x devices
-            }
-            setProgress();
-        }
-    }
-
-    @Override
-    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-        if (!fromUser) {
-            // We're not interested in programmatically generated changes to
-            // the progress bar's position.
-            return;
-        }
-
-        long duration = playerControl.getDuration();
-        long newPosition = (duration * progress) / 1000L;
-        playerControl.seekTo((int) newPosition);
-        binding.currentTimeText.setText(formatTime((int) newPosition));
-    }
-
-    /**
-     * Called in devices with touchpad when the user starts to adjust the position of the seekbar's thumb.
-     *
-     * Will be followed by several onProgressChanged notifications.
-     */
-    @Override
-    public void onStartTrackingTouch(SeekBar seekBar) {
-        isDragging = true;                           // monitors the duration of dragging
-        handler.removeMessages(SHOW_PROGRESS);     // grants no more updates with media player progress while dragging
-    }
-
-    /**
-     * Called in devices with touchpad when the user finishes the adjusting of the seekbar.
-     */
-    @Override
-    public void onStopTrackingTouch(SeekBar seekBar) {
-        isDragging = false;
-        setProgress();
-        updatePausePlay();
-        handler.sendEmptyMessage(SHOW_PROGRESS);    // grants future updates with media player progress
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        event.setClassName(MediaControlView.class.getName());
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        info.setClassName(MediaControlView.class.getName());
-    }
-}

+ 347 - 0
app/src/main/java/com/owncloud/android/media/MediaControlView.kt

@@ -0,0 +1,347 @@
+/*
+ * Nextcloud - Android Client
+ *
+ * SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
+ * SPDX-FileCopyrightText: 2022 Álvaro Brey Vilas <alvaro@alvarobrey.com>
+ * SPDX-FileCopyrightText: 2018-2020 Tobias Kaminsky <tobias@kaminsky.me>
+ * SPDX-FileCopyrightText: 2019 Chris Narkiewicz <hello@ezaquarii.com>
+ * SPDX-FileCopyrightText: 2018 Andy Scherzinger <info@andy-scherzinger.de>
+ * SPDX-FileCopyrightText: 2015 ownCloud Inc.
+ * SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
+ * SPDX-License-Identifier: GPL-2.0-only AND AGPL-3.0-or-later
+ */
+package com.owncloud.android.media
+
+import android.content.Context
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.util.AttributeSet
+import android.view.KeyEvent
+import android.view.LayoutInflater
+import android.view.View
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.widget.LinearLayout
+import android.widget.MediaController.MediaPlayerControl
+import android.widget.SeekBar
+import android.widget.SeekBar.OnSeekBarChangeListener
+import androidx.core.content.ContextCompat
+import com.owncloud.android.MainApp
+import com.owncloud.android.R
+import com.owncloud.android.databinding.MediaControlBinding
+import com.owncloud.android.lib.common.utils.Log_OC
+import com.owncloud.android.utils.theme.ViewThemeUtils
+import java.util.Formatter
+import java.util.Locale
+import javax.inject.Inject
+
+/**
+ * View containing controls for a MediaPlayer.
+ *
+ *
+ * Holds buttons "play / pause", "rewind", "fast forward" and a progress slider.
+ *
+ *
+ * It synchronizes itself with the state of the MediaPlayer.
+ */
+class MediaControlView(context: Context, attrs: AttributeSet?) :
+    LinearLayout(context, attrs),
+    View.OnClickListener,
+    OnSeekBarChangeListener {
+
+    private var playerControl: MediaPlayerControl? = null
+    private var binding: MediaControlBinding
+    private var isDragging = false
+
+    @Inject
+    lateinit var viewThemeUtils: ViewThemeUtils
+
+    public override fun onFinishInflate() {
+        super.onFinishInflate()
+    }
+
+    @Suppress("MagicNumber")
+    fun setMediaPlayer(player: MediaPlayerControl?) {
+        playerControl = player
+        handler.sendEmptyMessage(SHOW_PROGRESS)
+
+        handler.postDelayed({
+            updatePausePlay()
+            setProgress()
+        }, 100)
+    }
+
+    fun stopMediaPlayerMessages() {
+        handler.removeMessages(SHOW_PROGRESS)
+    }
+
+    @Suppress("MagicNumber")
+    private fun initControllerView() {
+        binding.playBtn.requestFocus()
+
+        binding.playBtn.setOnClickListener(this)
+        binding.forwardBtn.setOnClickListener(this)
+        binding.rewindBtn.setOnClickListener(this)
+
+        binding.progressBar.run {
+            viewThemeUtils.platform.themeHorizontalSeekBar(this)
+            setMax(1000)
+        }
+
+        binding.progressBar.setOnSeekBarChangeListener(this)
+
+        viewThemeUtils.material.run {
+            colorMaterialButtonPrimaryTonal(binding.rewindBtn)
+            colorMaterialButtonPrimaryTonal(binding.playBtn)
+            colorMaterialButtonPrimaryTonal(binding.forwardBtn)
+        }
+    }
+
+    /**
+     * Disable pause or seek buttons if the stream cannot be paused or seeked.
+     * This requires the control interface to be a MediaPlayerControlExt
+     */
+    private fun disableUnsupportedButtons() {
+        try {
+            if (playerControl?.canPause() == false) {
+                binding.playBtn.setEnabled(false)
+            }
+            if (playerControl?.canSeekBackward() == false) {
+                binding.rewindBtn.setEnabled(false)
+            }
+            if (playerControl?.canSeekForward() == false) {
+                binding.forwardBtn.setEnabled(false)
+            }
+        } catch (ex: IncompatibleClassChangeError) {
+            // We were given an old version of the interface, that doesn't have
+            // the canPause/canSeekXYZ methods. This is OK, it just means we
+            // assume the media can be paused and seeked, and so we don't disable
+            // the buttons.
+            Log_OC.i(TAG, "Old media interface detected")
+        }
+    }
+
+    @Suppress("MagicNumber")
+    private val handler: Handler = object : Handler(Looper.getMainLooper()) {
+        override fun handleMessage(msg: Message) {
+            if (msg.what == SHOW_PROGRESS) {
+                updatePausePlay()
+                val pos = setProgress()
+
+                if (!isDragging) {
+                    sendMessageDelayed(obtainMessage(SHOW_PROGRESS), (1000 - pos % 1000).toLong())
+                }
+            }
+        }
+    }
+
+    init {
+        MainApp.getAppComponent().inject(this)
+
+        val inflate = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+        binding = MediaControlBinding.inflate(inflate, this, true)
+        initControllerView()
+        isFocusable = true
+        setFocusableInTouchMode(true)
+        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS)
+        requestFocus()
+    }
+
+    @Suppress("MagicNumber")
+    private fun formatTime(timeMs: Int): String {
+        val totalSeconds = timeMs / 1000
+        val seconds = totalSeconds % 60
+        val minutes = totalSeconds / 60 % 60
+        val hours = totalSeconds / 3600
+        val mFormatBuilder = StringBuilder()
+        val mFormatter = Formatter(mFormatBuilder, Locale.getDefault())
+        return if (hours > 0) {
+            mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
+        } else {
+            mFormatter.format("%02d:%02d", minutes, seconds).toString()
+        }
+    }
+
+    @Suppress("MagicNumber")
+    private fun setProgress(): Int {
+        var position = 0
+        if (playerControl == null || isDragging) {
+            position = 0
+        }
+
+        playerControl?.let { playerControl ->
+            position = playerControl.currentPosition
+            val duration = playerControl.duration
+            if (duration > 0) {
+                // use long to avoid overflow
+                val pos = 1000L * position / duration
+                binding.progressBar.progress = pos.toInt()
+            }
+            val percent = playerControl.bufferPercentage
+            binding.progressBar.setSecondaryProgress(percent * 10)
+            val endTime = if (duration > 0) formatTime(duration) else "--:--"
+            binding.totalTimeText.text = endTime
+            binding.currentTimeText.text = formatTime(position)
+        }
+
+        return position
+    }
+
+    @Suppress("ReturnCount")
+    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+        val keyCode = event.keyCode
+        val uniqueDown = (event.repeatCount == 0 && event.action == KeyEvent.ACTION_DOWN)
+
+        when (keyCode) {
+            KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_SPACE -> {
+                if (uniqueDown) {
+                    doPauseResume()
+                    // show(sDefaultTimeout);
+                    binding.playBtn.requestFocus()
+                }
+                return true
+            }
+            KeyEvent.KEYCODE_MEDIA_PLAY -> {
+                if (uniqueDown && playerControl?.isPlaying == false) {
+                    playerControl?.start()
+                    updatePausePlay()
+                }
+                return true
+            }
+            KeyEvent.KEYCODE_MEDIA_STOP,
+            KeyEvent.KEYCODE_MEDIA_PAUSE
+            -> {
+                if (uniqueDown && playerControl?.isPlaying == true) {
+                    playerControl?.pause()
+                    updatePausePlay()
+                }
+                return true
+            }
+            else -> return super.dispatchKeyEvent(event)
+        }
+    }
+
+    fun updatePausePlay() {
+        binding.playBtn.icon = ContextCompat.getDrawable(
+            context,
+            if (playerControl?.isPlaying == true) {
+                R.drawable.ic_pause
+            } else { R.drawable.ic_play }
+        )
+        binding.forwardBtn.visibility = if (playerControl?.canSeekForward() == true) { VISIBLE } else { INVISIBLE }
+        binding.rewindBtn.visibility = if (playerControl?.canSeekBackward() == true) { VISIBLE } else { INVISIBLE }
+    }
+
+    private fun doPauseResume() {
+        playerControl?.run {
+            if (isPlaying) {
+                pause()
+            } else {
+                start()
+            }
+        }
+        updatePausePlay()
+    }
+
+    override fun setEnabled(enabled: Boolean) {
+        binding.playBtn.setEnabled(enabled)
+        binding.forwardBtn.setEnabled(enabled)
+        binding.rewindBtn.setEnabled(enabled)
+        binding.progressBar.setEnabled(enabled)
+
+        disableUnsupportedButtons()
+
+        super.setEnabled(enabled)
+    }
+
+    @Suppress("MagicNumber")
+    override fun onClick(v: View) {
+        var pos: Int
+
+        playerControl?.let { playerControl ->
+            val playing = playerControl.isPlaying
+            val id = v.id
+
+            when (id) {
+                R.id.playBtn -> {
+                    doPauseResume()
+                }
+                R.id.rewindBtn -> {
+                    pos = playerControl.currentPosition
+                    pos -= 5000
+                    playerControl.seekTo(pos)
+                    if (!playing) {
+                        playerControl.pause() // necessary in some 2.3.x devices
+                    }
+                    setProgress()
+                }
+                R.id.forwardBtn -> {
+                    pos = playerControl.currentPosition
+                    pos += 15000
+                    playerControl.seekTo(pos)
+
+                    if (!playing) {
+                        playerControl.pause() // necessary in some 2.3.x devices
+                    }
+
+                    setProgress()
+                }
+
+                else -> {
+                }
+            }
+        }
+    }
+
+    @Suppress("MagicNumber")
+    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+        if (!fromUser) {
+            // We're not interested in programmatically generated changes to
+            // the progress bar's position.
+            return
+        }
+
+        playerControl?.let { playerControl ->
+            val duration = playerControl.duration.toLong()
+            val newPosition = duration * progress / 1000L
+            playerControl.seekTo(newPosition.toInt())
+            binding.currentTimeText.text = formatTime(newPosition.toInt())
+        }
+    }
+
+    /**
+     * Called in devices with touchpad when the user starts to adjust the position of the seekbar's thumb.
+     *
+     * Will be followed by several onProgressChanged notifications.
+     */
+    override fun onStartTrackingTouch(seekBar: SeekBar) {
+        isDragging = true // monitors the duration of dragging
+        handler.removeMessages(SHOW_PROGRESS) // grants no more updates with media player progress while dragging
+    }
+
+    /**
+     * Called in devices with touchpad when the user finishes the adjusting of the seekbar.
+     */
+    override fun onStopTrackingTouch(seekBar: SeekBar) {
+        isDragging = false
+        setProgress()
+        updatePausePlay()
+        handler.sendEmptyMessage(SHOW_PROGRESS) // grants future updates with media player progress
+    }
+
+    override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
+        super.onInitializeAccessibilityEvent(event)
+        event.setClassName(MediaControlView::class.java.getName())
+    }
+
+    override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
+        super.onInitializeAccessibilityNodeInfo(info)
+        info.setClassName(MediaControlView::class.java.getName())
+    }
+
+    companion object {
+        private val TAG = MediaControlView::class.java.getSimpleName()
+        private const val SHOW_PROGRESS = 1
+    }
+}

+ 15 - 0
app/src/main/res/drawable/ic_fast_forward.xml

@@ -0,0 +1,15 @@
+<!--
+  ~ Nextcloud - Android Client
+  ~
+  ~ SPDX-FileCopyrightText: 2018-2024 Google LLC
+  ~ SPDX-License-Identifier: Apache-2.0
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M100,720v-480l360,240 -360,240ZM500,720v-480l360,240 -360,240Z"/>
+</vector>

+ 15 - 0
app/src/main/res/drawable/ic_fast_rewind.xml

@@ -0,0 +1,15 @@
+<!--
+  ~ Nextcloud - Android Client
+  ~
+  ~ SPDX-FileCopyrightText: 2018-2024 Google LLC
+  ~ SPDX-License-Identifier: Apache-2.0
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M860,720 L500,480l360,-240v480ZM460,720L100,480l360,-240v480Z"/>
+</vector>

+ 3 - 3
app/src/main/res/drawable/ic_pause.xml

@@ -9,7 +9,7 @@
     android:height="24dp"
     android:viewportWidth="960"
     android:viewportHeight="960">
-    <path
-        android:fillColor="@color/foreground_highlight"
-        android:pathData="M560,760L560,200L720,200L720,760L560,760ZM240,760L240,200L400,200L400,760L240,760Z" />
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M360,640h80v-320h-80v320ZM520,640h80v-320h-80v320ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880Z"/>
 </vector>

+ 4 - 5
app/src/main/res/drawable/ic_play.xml

@@ -1,9 +1,8 @@
 <!--
   ~ Nextcloud - Android Client
   ~
-  ~ SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
-  ~ SPDX-FileCopyrightText: 2023 Nextcloud GmbH
-  ~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
+  ~ SPDX-FileCopyrightText: 2018-2024 Google LLC
+  ~ SPDX-License-Identifier: Apache-2.0
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="24dp"
@@ -11,6 +10,6 @@
     android:viewportWidth="960"
     android:viewportHeight="960">
   <path
-      android:fillColor="@color/foreground_highlight"
-      android:pathData="M320,760v-560l440,280 -440,280Z"/>
+      android:fillColor="#FF000000"
+      android:pathData="m380,660 l280,-180 -280,-180v360ZM480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880Z"/>
 </vector>

+ 0 - 17
app/src/main/res/drawable/ripple.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Nextcloud - Android Client
-  ~
-  ~ SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
-  ~ SPDX-FileCopyrightText: 2022 Nextcloud GmbH
-  ~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/grey_200">
-    <item android:id="@android:id/mask">
-        <shape android:shape="oval">
-            <solid android:color="?android:colorPrimary" />
-        </shape>
-        <color android:color="@color/white" />
-    </item>
-</ripple>

+ 45 - 20
app/src/main/res/layout/media_control.xml

@@ -7,49 +7,76 @@
   ~ SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
   ~ SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    android:id="@+id/media_control_linear_layout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_marginBottom="@dimen/standard_double_margin"
     android:orientation="vertical">
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="50dp"
         android:gravity="center"
         android:orientation="horizontal"
         android:paddingTop="@dimen/standard_quarter_padding">
 
-        <ImageButton
+        <com.google.android.material.button.MaterialButton
             android:id="@+id/rewindBtn"
-            style="@android:style/MediaButton.Rew"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            app:backgroundTint="@color/transparent"
+            app:iconTint="@color/black"
+            app:iconGravity="top"
+            android:layout_marginEnd="@dimen/standard_half_margin"
+            android:paddingTop="@dimen/alternate_padding"
+            app:icon="@drawable/ic_fast_rewind"
             android:contentDescription="@string/media_rewind_description" />
 
-        <ImageButton
+        <com.google.android.material.button.MaterialButton
             android:id="@+id/playBtn"
-            style="@android:style/MediaButton.Play"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            app:backgroundTint="@color/transparent"
+            app:iconTint="@color/black"
+            app:iconGravity="top"
+            android:paddingTop="@dimen/alternate_padding"
+            app:icon="@drawable/ic_play"
+            android:layout_marginEnd="@dimen/standard_half_margin"
+
             android:contentDescription="@string/media_play_pause_description" />
 
-        <ImageButton
+        <com.google.android.material.button.MaterialButton
             android:id="@+id/forwardBtn"
-            style="@android:style/MediaButton.Ffwd"
+            android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="match_parent"
+            app:backgroundTint="@color/transparent"
+            app:iconTint="@color/black"
+            app:iconGravity="top"
+            android:paddingTop="@dimen/alternate_padding"
+            app:icon="@drawable/ic_fast_forward"
             android:contentDescription="@string/media_forward_description" />
 
     </LinearLayout>
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="50dp"
+        android:gravity="center"
         android:orientation="horizontal">
 
         <TextView
             android:id="@+id/currentTimeText"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:paddingStart="@dimen/standard_quarter_padding"
-            android:paddingTop="@dimen/standard_quarter_padding"
-            android:paddingEnd="@dimen/standard_quarter_padding"
+            android:layout_height="match_parent"
+            android:padding="@dimen/standard_quarter_padding"
+            android:gravity="center"
             android:text="@string/placeholder_media_time"
             android:textColor="@color/text_color"
             android:textSize="@dimen/two_line_secondary_text_size"
@@ -59,7 +86,7 @@
             android:id="@+id/progressBar"
             style="?android:attr/progressBarStyleHorizontal"
             android:layout_width="0dp"
-            android:layout_height="@dimen/seek_bar_height"
+            android:layout_height="match_parent"
             android:layout_weight="1"
             android:splitTrack="false"
             tools:ignore="UnusedAttribute" />
@@ -67,11 +94,9 @@
         <TextView
             android:id="@+id/totalTimeText"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:paddingStart="@dimen/standard_quarter_padding"
-            android:paddingTop="@dimen/standard_quarter_padding"
-            android:paddingEnd="@dimen/standard_quarter_padding"
+            android:layout_height="match_parent"
+            android:padding="@dimen/standard_quarter_padding"
+            android:gravity="center"
             android:text="@string/placeholder_media_time"
             android:textColor="@color/text_color"
             android:textSize="@dimen/two_line_secondary_text_size"

+ 0 - 1
app/src/main/res/values/colors.xml

@@ -53,7 +53,6 @@
     <color name="nc_grey">#ededed</color>
     <color name="icon_on_nc_grey">#000000</color>
     <color name="foreground_highlight">#1D1B1E</color>
-
     <color name="process_dialog_background">#ffffff</color>
     <color name="indicator_dot_selected">#ffffff</color>
     <color name="drawer_shadow">#000000</color>

+ 0 - 1
app/src/main/res/values/dims.xml

@@ -78,7 +78,6 @@
     <dimen name="file_download_fragment_display_text_margin">40dp</dimen>
     <dimen name="drawer_width">240dp</dimen>
     <dimen name="grid_item_text_size">16sp</dimen>
-    <dimen name="seek_bar_height">32dp</dimen>
     <dimen name="search_users_groups_layout_width">200dp</dimen>
     <dimen name="search_users_groups_layout_list_view_margin">20dp</dimen>
     <dimen name="share_file_layout_text_size">12sp</dimen>