aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/pictureInPicture.tsx83
-rw-r--r--src/utils/constants.ts6
2 files changed, 88 insertions, 1 deletions
diff --git a/src/plugins/pictureInPicture.tsx b/src/plugins/pictureInPicture.tsx
new file mode 100644
index 0000000..7a9e790
--- /dev/null
+++ b/src/plugins/pictureInPicture.tsx
@@ -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 })
+});
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 245c8bb..400fcaa 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -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