Skip to content

Commit ced95e2

Browse files
committed
Picture in Picture
1 parent 82702c5 commit ced95e2

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

features/features.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
[
2+
{
3+
"version": 2,
4+
"id": "picture-in-picture",
5+
"versionAdded": "v4.0.0"
6+
},
27
{
38
"version": 2,
49
"id": "studio-creation-date",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"title": "Picture in Picture",
3+
"description": "Adds a button for opening a picture in picture for projects.",
4+
"credits": [
5+
{
6+
"username": "stio_studio",
7+
"url": "https://stio.studio/"
8+
}
9+
],
10+
"type": ["Website"],
11+
"tags": ["New", "Featured"],
12+
"dynamic": true,
13+
"scripts": [
14+
{
15+
"file": "picture-in-picture.js",
16+
"runOn": "/projects/*"
17+
}
18+
],
19+
"components": [{
20+
"type": "info",
21+
"content": "Picture in Picture does NOT have inputs, of any kind. This means that it can mostly only be used for watching."
22+
}]
23+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
export default async function ({ feature, console }) {
2+
const canvas = feature.traps.vm.renderer.canvas;
3+
4+
let video = document.createElement("video");
5+
// video.setAttribute("controls", "controls");
6+
video.setAttribute("autoplay", "autoplay");
7+
video.setAttribute("style", "width: 100%; height: 100%");
8+
// document.querySelector(".preview .inner").append(video);
9+
10+
video.srcObject = canvas.captureStream(30)
11+
12+
await new Promise(async (resolve, reject) => {
13+
(async () => {
14+
const rem = await ScratchTools.waitForElement(".preview .inner .flex-row.action-buttons")
15+
resolve(rem);
16+
})();
17+
(async () => {
18+
const rem = await ScratchTools.waitForElement(".menu-bar_account-info-group_MeJZP")
19+
resolve(rem);
20+
})();
21+
})
22+
23+
let openPopup = document.createElement("button");
24+
25+
ScratchTools.waitForElements(".preview .inner .flex-row.action-buttons", async function (row) {
26+
if (row.querySelector(".ste-video-recorder-open")) return;
27+
openPopup = document.createElement("button");
28+
openPopup.className = "button action-button ste-video-recorder-open";
29+
openPopup.textContent = "Picture in Picture";
30+
row.insertAdjacentElement("afterbegin", openPopup);
31+
openPopup.addEventListener('click', () => {
32+
popup()
33+
})
34+
})
35+
ScratchTools.waitForElements(".menu-bar_account-info-group_MeJZP", async function (row) {
36+
if (row.querySelector(".ste-video-recorder-open")) return;
37+
openPopup = document.createElement("div");
38+
openPopup.className = "menu-bar_menu-bar-item_oLDa- menu-bar_hoverable_c6WFB";
39+
let rem = document.createElement("div");
40+
rem.textContent = "Picture in Picture";
41+
openPopup.append(rem);
42+
row.insertAdjacentElement("afterbegin", openPopup);
43+
openPopup.addEventListener('click', () => {
44+
popup()
45+
})
46+
})
47+
48+
function popup() {
49+
try {
50+
video.requestPictureInPicture()
51+
}
52+
catch {
53+
console.log("Picture in Picture not supported or failed to request")
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)