question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Custom Controls on iOS

See original GitHub issue

I am using usePlyr to create a custom plyr instance but on mobile the audio controls don’t work. The icon shows as unmuted and doesn’t unmute the audio when tapped. Has anyone else had this issue?

import React, { useState, useContext } from "react";

import type { APITypes } from "plyr-react";

import { usePlyr, PlyrProps, PlyrInstance } from "plyr-react";

import styles from "./Play.module.scss";

import { CoreContext } from "~context";
import hexToRgb from "~shared/utils/hexToRgb";

import { useGTM } from "~hooks/useGTM";

const CustomPlyr = React.forwardRef<APITypes, PlyrProps>((props, ref: any) => {
    const { playerStyle, size }: any = useContext(CoreContext);

    const { track } = useGTM();

    const { source, options = null } = props;

    const raptorRef = usePlyr(ref, { options, source });

    const { poster } = source || {};
    const { active } = options?.loop || {};
    const { autoplay } = options || {};

    const { gradient, subtitles, ui, full } = playerStyle;

    const [current, setCurrent] = useState(0);
    const [progress, setProgress] = useState(0);
    const [playing, setPlaying] = useState(autoplay);
    const [muted, setMuted] = useState(true);
    const [showLoopScreen, setShowLoop] = useState(false);
    const [counter, setCounter] = useState<number>(0);

    React.useEffect(() => {
        if (ref?.current?.plyr?.source === null) return;
        const api = ref?.current as { plyr: PlyrInstance };

        setMuted(api?.plyr?.volume === 0);

        const canPlay = () => {
            if (autoplay && !playing) {
                api?.plyr?.play();
            }
        };

        const onPlay = () => {
            setShowLoop(false);
            setPlaying(true);
        };

        const onPause = () => {
            setPlaying(false);
        };

        const onEnded = () => {
            setShowLoop(!active);
            setCounter(0);
            track({
                category: "adops",
                adOpsAction: "video",
                adOpsLabel: `video-completed`,
                event: "coreDataPush",
            });
        };

        const onUpdate = () => {
            setCurrent(Math.round(api?.plyr?.currentTime));

            if (api?.plyr?.paused === false) {
                if (current > 0.5) {
                    setProgress(
                        Number(
                            (api?.plyr?.currentTime / api?.plyr?.duration) * 100
                        )
                    );

                    if (progress > 1 && counter === 0) {
                        setCounter(1);
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `video-start`,
                            event: "coreDataPush",
                        });
                    }
                    if (progress > 25 && counter === 1) {
                        setCounter(2);
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `'video-played-25-percent`,
                            event: "coreDataPush",
                        });
                    }
                    if (progress > 50 && counter === 2) {
                        setCounter(3);
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `'video-played-50-percent`,
                            event: "coreDataPush",
                        });
                    }
                    if (progress > 75 && counter === 3) {
                        setCounter(4);
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `'video-played-75-percent`,
                            event: "coreDataPush",
                        });
                    }
                    if (progress < 5 && counter === 4) {
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `video-completed`,
                            event: "coreDataPush",
                        });
                        setShowLoop(!active);
                        track({
                            category: "adops",
                            adOpsAction: "video",
                            adOpsLabel: `video-start`,
                            event: "coreDataPush",
                        });
                        setCounter(1);
                    }
                }
            }
        };

        api?.plyr?.on("canplay", canPlay);
        api?.plyr?.on("playing", onPlay);
        api?.plyr?.on("pause", onPause);
        api?.plyr?.on("timeupdate", onUpdate);
        api?.plyr?.on("ended", onEnded);

        const offFuncs = () => {
            api?.plyr?.off("canplay", canPlay);
            api?.plyr?.off("playing", onPlay);
            api?.plyr?.off("pause", onPause);
            api?.plyr?.off("timeupdate", onUpdate);
            api?.plyr?.off("ended", onEnded);
        };

        if (ref?.current?.plyr?.source) {
            return offFuncs;
        }
    });

    if (!source || !ref) {
        return null;
    }

    return (
        <div
            data-size={size}
            data-full={full}
            className={styles.playercontainer}
        >
            {showLoopScreen || (!autoplay && current < 1 && !playing) ? (
                <div
                    className={styles.loopscreen}
                    style={{
                        backgroundImage: `url(${poster})`,
                    }}
                >
                    {!autoplay && current < 1 && !playing ? (
                        <svg
                            viewBox="0 0 503 612"
                            xmlns="http://www.w3.org/2000/svg"
                        >
                            <path
                                fill={ui?.color}
                                d="M0 608.7l503.2-302.6L0 3.5z"
                            />
                        </svg>
                    ) : (
                        <svg viewBox="0 0 425.47 402.84">
                            <g>
                                <path
                                    className="st0"
                                    fill="white"
                                    d="M138.18 396.9c-10.19-7.86-20.46-15.61-30.56-23.6-16.19-12.81-32.27-25.76-48.38-38.66-7.39-5.92-7.53-12.7-.3-18.51 24.41-19.58 48.87-39.09 73.26-58.69 4.09-3.28 8.27-5.07 13.27-2.24 3.92 2.22 5.33 5.76 5.31 10.13-.06 12.89-.02 25.78-.02 39.35h4.97c46.14 0 92.29.11 138.43-.04 41.76-.13 74.9-27.79 82.55-68.79 2.98-15.96.89-31.48-5.42-46.39-2.3-5.42-3.1-10.8-1.14-16.44 2.78-8.01 10.02-13.41 18.62-13.9 8.19-.47 16.06 4.3 19.68 12.32 7.4 16.4 10.93 33.63 10.72 51.64-.77 67.34-53.92 121.52-121.27 122.55-46.94.71-93.9.18-140.85.2h-6.3v22.05c0 4.84-.33 9.71.08 14.51.56 6.71-1.71 11.56-7.82 14.51h-4.83zM274.71 98.24c-2.04-.09-3.61-.23-5.18-.23-45.98-.01-91.96-.09-137.95.02-42 .1-75.29 27.77-82.89 68.98-2.94 15.95-.82 31.48 5.54 46.38 2.31 5.42 3 10.82.98 16.44-2.88 8.02-10.17 13.36-18.73 13.73-8.26.36-15.93-4.44-19.56-12.51-7.38-16.42-10.87-33.65-10.64-51.66.87-67.32 54.04-121.34 121.46-122.34 46.94-.7 93.9-.17 140.85-.19h6.12V25.92c0-2.42.11-4.85-.02-7.26-.27-5.08 1.12-9.31 5.98-11.67 4.95-2.4 8.95-.32 12.83 2.8 13.05 10.53 26.19 20.97 39.29 31.44 10.83 8.66 21.67 17.31 32.5 25.98 8.82 7.06 8.8 13.35-.03 20.4-23.56 18.83-47.11 37.68-70.66 56.52-1.01.81-2.02 1.6-3.05 2.38-3.54 2.68-7.34 3.23-11.31 1.1-3.75-2.01-5.52-5.26-5.52-9.51 0-11.45 0-22.91-.01-34.36v-5.5z"
                                />
                            </g>
                        </svg>
                    )}
                </div>
            ) : (
                <div
                    style={{
                        backgroundColor:
                            hexToRgb(gradient?.color, 0.75) ||
                            "rgba(0,0,0, .75)",
                    }}
                    className={styles.overlay}
                >
                    <div
                        style={{ backgroundColor: size === "one" && ui?.color }}
                        className={styles.circle}
                    >
                        {current < 60 && (
                            <span
                                style={{
                                    color:
                                        size === "one"
                                            ? gradient?.color
                                            : ui?.color,
                                }}
                            >
                                {current}
                            </span>
                        )}
                        <svg fill="rgba(0,0,0,0)" className={styles.progress}>
                            <circle
                                cx="25"
                                cy="25"
                                r="22"
                                style={{
                                    backgroundColor: "none",
                                    stroke:
                                        hexToRgb(`${ui?.color}`, 0.4) ||
                                        "white",
                                }}
                                className={styles.track}
                            />
                            <circle
                                cx="25"
                                cy="25"
                                r="22"
                                className={styles.pct}
                                style={{
                                    backgroundColor: "none",
                                    stroke: ui?.color,
                                    strokeDashoffset: `${
                                        (1 - progress / 200) *
                                        (2 * (22 / 7) * 40)
                                    }`,
                                }}
                            />
                        </svg>
                    </div>
                    <button
                        onClick={() => {
                            ref.current.plyr.togglePlay();
                        }}
                        className={styles.action}
                    >
                        {playing ? (
                            <svg
                                viewBox="0 0 503 594"
                                xmlns="http://www.w3.org/2000/svg"
                            >
                                <path
                                    fill={ui?.color}
                                    d="M2.2 2.2h174.2V594H2.2zM328.8 2.2H503V594H328.8z"
                                />
                            </svg>
                        ) : (
                            <svg
                                viewBox="0 0 503 612"
                                xmlns="http://www.w3.org/2000/svg"
                            >
                                <path
                                    fill={ui?.color}
                                    d="M0 608.7l503.2-302.6L0 3.5z"
                                />
                            </svg>
                        )}
                    </button>
                    <button
                        onClick={() => {
                            if (muted) {
                                ref.current.plyr.increaseVolume(1);
                            } else {
                                ref.current.plyr.decreaseVolume(1);
                            }
                        }}
                        className={styles.volume}
                    >
                        {muted ? (
                            <svg viewBox="0 0 510.75 511.76">
                                <path
                                    fill={ui?.color}
                                    d="M474.37 511.76h-1c-1.15-1.37-2.2-2.85-3.46-4.11-15.75-15.76-31.56-31.47-47.27-47.27-2.1-2.11-3.75-4.65-5.65-7.03-31.84 25.6-66.21 42.9-104.69 51.7-.32-.67-.59-.96-.59-1.25-.05-18.13-.14-36.25.05-54.37.01-1.32 1.92-3.19 3.38-3.83 9.26-4.07 18.98-7.21 27.89-11.92 11.17-5.91 21.7-13.02 32.04-19.33L254.62 293.9v188.32c-.42.19-.83.37-1.25.56-1.15-1.43-2.18-2.97-3.47-4.26-44.54-44.59-89.13-89.13-133.63-133.76-2.41-2.42-4.79-3.48-8.25-3.47-33.26.13-66.52.08-99.78.06-2.99 0-5.97-.16-8.96-.25V171.43c1.99-.09 3.97-.25 5.96-.25 40.56-.01 81.13-.01 121.69-.01h6.19c-1.83-2.01-2.78-3.12-3.81-4.15C87.13 124.8 44.93 82.6 2.71 40.43 1.68 39.41.44 38.6-.69 37.69v-1C11.03 24.46 22.75 12.24 34.3.19c159.26 159.26 317.32 317.32 476.51 476.5-12.04 11.58-24.24 23.32-36.44 35.07zM311.62 7.81c162.83 35.77 247.51 220.81 169.16 366.17-13.68-13.73-27.33-27.31-40.74-41.12-1.02-1.05-.8-3.88-.34-5.68 3.86-15.42 8.84-30.62 11.7-46.21 4.68-25.57 2-51.06-4.76-76.02-12.4-45.82-38.19-82.54-76.6-110.33-16.25-11.76-33.98-20.82-53.16-26.78-4.35-1.35-5.45-3.36-5.37-7.69.28-15.63.11-31.26.11-46.89V7.81z"
                                />
                                <path
                                    fill={ui?.color}
                                    d="M380.93 274.35c-6.71-6.8-12.73-12.96-18.82-19.06-15.84-15.88-31.74-31.7-47.51-47.65-1.38-1.39-2.83-3.53-2.85-5.33-.2-19.76-.13-39.53-.13-59.39 41.15 17.18 78.7 71.35 69.31 131.43zM196.95 88c18.71-18.67 38.08-37.99 57.47-57.33v114.81c-18.81-18.81-38.11-38.12-57.47-57.48z"
                                />
                            </svg>
                        ) : (
                            <svg viewBox="0 0 510.75 511.76">
                                <path
                                    fill={ui?.color}
                                    d="M0 170.93c2.98-.09 5.97-.25 8.95-.25 33.25-.02 66.51-.06 99.76.06 3.45.01 5.84-1.04 8.25-3.46 44.49-44.62 89.07-89.16 133.61-133.73 1.29-1.29 2.34-2.82 4.47-3.71v452.25c-1.55-1.43-2.87-2.57-4.1-3.8-44.57-44.55-89.15-89.08-133.63-133.71-2.67-2.67-5.3-3.83-9.1-3.82-34.08.14-68.17.09-102.25.07-1.99 0-3.98-.16-5.97-.25C0 284.04 0 227.48 0 170.93zM312.32 504.13v-35.44c0-5.99.24-11.99-.09-17.96-.2-3.65 1.11-5.22 4.53-6.29 21.61-6.77 41.38-17.18 59.28-31.04 39-30.19 64.03-69.36 73.94-117.68 17.18-83.77-20.14-167.68-94.04-211.03-12.36-7.25-26.17-12.05-39.45-17.67-3.04-1.29-4.31-2.52-4.27-6 .21-17.78.1-35.56.1-53.4 90.78 17.36 187.77 102.27 197.57 226.6 11.55 146.59-94.73 249.1-197.57 269.91z"
                                />
                                <path
                                    fill={ui?.color}
                                    d="M312.63 142.19c36.6 16.84 71.16 59.71 70.6 114.87-.57 55.95-36.91 97.18-70.6 112.3V142.19z"
                                />
                            </svg>
                        )}
                    </button>
                </div>
            )}
            <video
                ref={raptorRef as React.MutableRefObject<HTMLVideoElement>}
                className="plyr-react plyr"
            />
        </div>
    );
});

CustomPlyr.displayName = "CustomPlyr";

export default CustomPlyr;

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:14 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
c-mellacommented, Sep 15, 2022

@realamirhe Thanks again for looking into it, I’m not sure what the issue is but I and my teammates are still seeing the video as muted no matter how much we click the unmute button. I’m not sure if this helps but I’m on an iPhone 13 running iOS 15.6

1reaction
c-mellacommented, Aug 31, 2022

I removed a lot of the dynamic aspects of the code and replaced it with hard coded values in order to make the test work but here is the sample code for you to review.

https://codepen.io/c-mella/pen/JjvPRjM

Thanks again for you help

Read more comments on GitHub >

github_iconTop Results From Across the Web

Edit Control Center on your iPhone, iPad, and iPod touch
You can customize Control Center by adding controls for apps, settings, and features like Camera, Music Recognition, Dark Mode, and more.
Read more >
iOS: How to customize Control Center on iPhone and iPad
Tap on Settings · Swipe down and tap Control Center · Tap the next to any item you'd like to add under “More...
Read more >
Cocoa Controls: Custom Controls for iOS, iPadOS, macOS ...
6,674 open source UI components for iOS, iPadOS, macOS, tvOS, and watchOS. Stay in touch.
Read more >
Custom Controls in iOS | Kodeco, the new raywenderlich.com
Custom controls are an important part of developing apps for iOS, allowing you to develop engaging user experiences, while achieving great code separability ......
Read more >
How to customize and use Control Center on iPhone
How to customize Control Center on iPhone · Launch the Settings app on your iPhone. · Tap Control Centre. Tap on Control Centre...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found