feat(plugin): PictureInPicture (#1697)
Co-authored-by: V <vendicated@riseup.net>
This commit is contained in:
parent
885c75fdaa
commit
4c9996d620
2 changed files with 88 additions and 1 deletions
83
src/plugins/pictureInPicture.tsx
Normal file
83
src/plugins/pictureInPicture.tsx
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2023 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { React, Tooltip } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
loop: {
|
||||
description: "Whether to make the PiP video loop or not",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
restartNeeded: false
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "PictureInPicture",
|
||||
description: "Adds picture in picture to videos (next to the Download button)",
|
||||
authors: [Devs.Lumap],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ".onRemoveAttachment,",
|
||||
replacement: {
|
||||
match: /\.nonMediaAttachment.{0,10}children:\[(\i),/,
|
||||
replace: "$&$1&&$self.renderPiPButton(),"
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
renderPiPButton: ErrorBoundary.wrap(() => {
|
||||
return (
|
||||
<Tooltip text="Toggle Picture in Picture">
|
||||
{tooltipProps => (
|
||||
<div
|
||||
{...tooltipProps}
|
||||
role="button"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
paddingTop: "4px",
|
||||
paddingLeft: "4px",
|
||||
paddingRight: "4px",
|
||||
}}
|
||||
onClick={e => {
|
||||
const video = e.currentTarget.parentNode!.parentNode!.querySelector("video")!;
|
||||
const videoClone = document.body.appendChild(video.cloneNode(true)) as HTMLVideoElement;
|
||||
|
||||
videoClone.loop = settings.store.loop;
|
||||
videoClone.style.display = "none";
|
||||
videoClone.onleavepictureinpicture = () => videoClone.remove();
|
||||
|
||||
function launchPiP() {
|
||||
videoClone.currentTime = video.currentTime;
|
||||
videoClone.requestPictureInPicture();
|
||||
video.pause();
|
||||
videoClone.play();
|
||||
}
|
||||
|
||||
if (videoClone.readyState === 4 /* HAVE_ENOUGH_DATA */)
|
||||
launchPiP();
|
||||
else
|
||||
videoClone.onloadedmetadata = launchPiP;
|
||||
}}
|
||||
>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="var(--interactive-normal)"
|
||||
d="M21 3a1 1 0 0 1 1 1v7h-2V5H4v14h6v2H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h18zm0 10a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h8zm-1 2h-6v4h6v-4z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</Tooltip>
|
||||
);
|
||||
}, { noop: true })
|
||||
});
|
|
@ -355,6 +355,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||
name: "bb010g",
|
||||
id: 72791153467990016n,
|
||||
},
|
||||
Lumap: {
|
||||
name: "lumap",
|
||||
id: 635383782576357407n
|
||||
},
|
||||
Dolfies: {
|
||||
name: "Dolfies",
|
||||
id: 852892297661906993n,
|
||||
|
@ -362,7 +366,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({
|
|||
RuukuLada: {
|
||||
name: "RuukuLada",
|
||||
id: 119705748346241027n,
|
||||
},
|
||||
}
|
||||
} satisfies Record<string, Dev>);
|
||||
|
||||
// iife so #__PURE__ works correctly
|
||||
|
|
Loading…
Reference in a new issue