mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-24 11:58:37 +00:00
Merge pull request #976 from samthe13th/iframe-sandbox-v2
Refactor and redesign iframe.html
This commit is contained in:
commit
184d206ee0
326
iframe-examples.js
Normal file
326
iframe-examples.js
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/**
|
||||||
|
* SANDBOX EXAMPLE CONFIG
|
||||||
|
*
|
||||||
|
* options: (number | boolean | string | null)[]
|
||||||
|
* - OPTIONAL if using a user input; see "input" below
|
||||||
|
* - List of values to test (passed into "result" function)
|
||||||
|
* - An option button will be generated for each value in the list
|
||||||
|
*
|
||||||
|
* input: object
|
||||||
|
* - OPTIONAL
|
||||||
|
* - User input for testing (eg a range slider).
|
||||||
|
* - Output of element onchange will be passed into RESULT function.
|
||||||
|
*
|
||||||
|
* labels: string[]
|
||||||
|
* - OPTIONAL
|
||||||
|
* - List of labels for option buttons (should be same length as options list).
|
||||||
|
* - If no labels are provided, option buttons are labeled with their value
|
||||||
|
*
|
||||||
|
* result: (value: any) => object
|
||||||
|
* - Function that returns a postMessage object
|
||||||
|
* - Based on the value produced by an option button, or a user input
|
||||||
|
*/
|
||||||
|
|
||||||
|
const IFRAME_API = {
|
||||||
|
add: {
|
||||||
|
options: [true],
|
||||||
|
labels: ["Video with styles"],
|
||||||
|
result: value => ({
|
||||||
|
"target": "*",
|
||||||
|
"add": value,
|
||||||
|
"settings": { "style": "width:640px;height:360px;float:left;border:10px solid red;display:block;"}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
automixer: {
|
||||||
|
options: [true, false],
|
||||||
|
result: value => ({ "automixer": value })
|
||||||
|
},
|
||||||
|
bitrate: {
|
||||||
|
options: [-1],
|
||||||
|
labels: ["default (-1)"],
|
||||||
|
input: {
|
||||||
|
title: "bitrate",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 6000,
|
||||||
|
value: 3000
|
||||||
|
},
|
||||||
|
result: value => ({ "bitrate": value, "target": "*" })
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ "camera": value })
|
||||||
|
},
|
||||||
|
changeAudioDevice: { // change text of add camera button
|
||||||
|
options: [1,2,3,4],
|
||||||
|
result: value => ({ "changeAudioDevice": value })
|
||||||
|
},
|
||||||
|
changeVideoDevice: { // change text of add camera button
|
||||||
|
options: [1,2,3,4],
|
||||||
|
result: value => ({ "changeVideoDevice": value })
|
||||||
|
},
|
||||||
|
close: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "close": value })
|
||||||
|
},
|
||||||
|
getDetailedState: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getDetailedState": value }),
|
||||||
|
},
|
||||||
|
getDeviceList: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getDeviceList": value }),
|
||||||
|
},
|
||||||
|
getLoudness: {
|
||||||
|
options: [false, true],
|
||||||
|
result: value => ({ "getLoudness": value }),
|
||||||
|
},
|
||||||
|
getStreamIDs: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "getStreamIDs": value }),
|
||||||
|
},
|
||||||
|
keyframe: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "keyframe": value }),
|
||||||
|
},
|
||||||
|
mute: {
|
||||||
|
options: [
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
"toggle" // open to a better suggestion here.
|
||||||
|
],
|
||||||
|
result: value => ({ "mute": value }),
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [true, false, "toggle"],
|
||||||
|
result: value => ({ "mic": value }),
|
||||||
|
},
|
||||||
|
panning: {
|
||||||
|
options: [0, 180, 90],
|
||||||
|
input: {
|
||||||
|
title: "panning",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 180,
|
||||||
|
value: 90
|
||||||
|
},
|
||||||
|
labels: ["Left (0)", "Right (180)", "Center (90)"],
|
||||||
|
result: value => ({ "panning": value }),
|
||||||
|
},
|
||||||
|
previewWebcam: {
|
||||||
|
options: ["previewWebcam"], // publishScreen
|
||||||
|
result: value => ({ "function": value }),
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
options: [true, false],
|
||||||
|
result: value => ({ "record": value }),
|
||||||
|
},
|
||||||
|
reload: {
|
||||||
|
options: [true],
|
||||||
|
result: value => ({ "reload": value }),
|
||||||
|
},
|
||||||
|
remove: { // target can be a stream ID or * for all.
|
||||||
|
options: [true],
|
||||||
|
labels: ["Target video"],
|
||||||
|
result: value => ({ "target": "*", "remove": value })
|
||||||
|
},
|
||||||
|
sendChat: {
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "Hello"
|
||||||
|
},
|
||||||
|
result: value => ({ "sendChat": value }),
|
||||||
|
},
|
||||||
|
sceneState: {
|
||||||
|
options: [true, false],
|
||||||
|
labels: ["ENABLE TALLY LIGHT (true)", "STOP TALLY LIGHT (false)"],
|
||||||
|
result: value => ({ "sceneState": value })
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
options: ["#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}"],
|
||||||
|
labels: ["Insert Style Sheet"],
|
||||||
|
result: value => ({ "style": value }),
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ "volume": value }),
|
||||||
|
},
|
||||||
|
["function: Eval"]: {
|
||||||
|
options: ["eval"], // publishScreen
|
||||||
|
result: value => ({ "function": value, "value": 'alert(\"DANGERUS\")' })
|
||||||
|
},
|
||||||
|
["function: Change html"]: {
|
||||||
|
options: ["changeHTML"], // change text of add camera button
|
||||||
|
result: value => ({ "function": value, "target": "add_camera", "value": "NEW CAMERA TEXT" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const COMPANION_API = { // list available commands to console
|
||||||
|
bitrate: {
|
||||||
|
input: {
|
||||||
|
title: "bitrate",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 6000,
|
||||||
|
value: 3000
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, action: "bitrate", value })
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "camera", value })
|
||||||
|
},
|
||||||
|
forceKeyframe: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Rainbow puke fix"],
|
||||||
|
result: value => ({ target: null, action: "forceKeyframe", value }),
|
||||||
|
},
|
||||||
|
getDetails: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "getDetails", value })
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
options: [1,2,3,4,5,6,7,8],
|
||||||
|
result: value => ({ target: null, action: "group", value })
|
||||||
|
},
|
||||||
|
hangup: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "hangup", value })
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "mic", value })
|
||||||
|
},
|
||||||
|
panning: {
|
||||||
|
options: [0, 180, 90],
|
||||||
|
input: {
|
||||||
|
title: "panning",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 180,
|
||||||
|
value: 90
|
||||||
|
},
|
||||||
|
labels: ["Left (0)", "Right (180)", "Center (90)"],
|
||||||
|
result: value => ({ target: null, action: "panning", value })
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "record", value })
|
||||||
|
},
|
||||||
|
reload: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "reload", value })
|
||||||
|
},
|
||||||
|
sendChat: {
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "Hello"
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, action: "sendChat", value }),
|
||||||
|
},
|
||||||
|
speaker: { // "speaker" also works in the same way
|
||||||
|
options: [false, true, "toggle"],
|
||||||
|
result: value => ({ target: null, action: "speaker", value }),
|
||||||
|
},
|
||||||
|
togglehand: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "togglehand", value }),
|
||||||
|
},
|
||||||
|
togglescreenshare: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ target: null, action: "togglescreenshare", value }),
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ target: null, "action": "volume", value }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function guestTargetedAPI(target) {
|
||||||
|
return {
|
||||||
|
addScene: {
|
||||||
|
options: [null,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "scene321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "addScene", target, value })
|
||||||
|
},
|
||||||
|
display: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "display", target, value })
|
||||||
|
},
|
||||||
|
forward: {
|
||||||
|
options: [null],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "room321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "forward", target, value })
|
||||||
|
},
|
||||||
|
forceKeyframe: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Rainbow puke fix"],
|
||||||
|
result: value => ({ "action": "forceKeyframe", target, value })
|
||||||
|
},
|
||||||
|
hangup: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "hangup", target, value })
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
options: [0,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "group321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "group", target, value })
|
||||||
|
},
|
||||||
|
soloChat: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "soloChat", target, value })
|
||||||
|
},
|
||||||
|
soloVideo: {
|
||||||
|
options: [null],
|
||||||
|
result: value => ({ "action": "soloVideo", target, value })
|
||||||
|
},
|
||||||
|
speaker: {
|
||||||
|
options: [null],
|
||||||
|
labels: ["Remote speaker"],
|
||||||
|
result: value =>({ "action": "speaker", target, value })
|
||||||
|
},
|
||||||
|
mic: {
|
||||||
|
options: [null],
|
||||||
|
result: value =>({ "action": "mic", target, value })
|
||||||
|
},
|
||||||
|
muteScene: {
|
||||||
|
options: [null,1,2,3,4,5,6,7,8],
|
||||||
|
input: {
|
||||||
|
type: "text",
|
||||||
|
value: "scene321"
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "muteScene", target, value })
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
input: {
|
||||||
|
title: "volume",
|
||||||
|
type: "range",
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
value: 100
|
||||||
|
},
|
||||||
|
result: value => ({ "action": "volume", target, value }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
200
iframe.css
Normal file
200
iframe.css
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #e1e8fc;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 5px;
|
||||||
|
background: white;
|
||||||
|
border: solid;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:last-child) {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
max-width: 300px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewlink {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section > h4:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post > * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post > button {
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-post-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: solid 5px #4d66a8;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
overflow: auto;
|
||||||
|
background: white;
|
||||||
|
width: 350px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-body {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
background: #4d66a8;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-header > button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-example {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: solid #4d66a8 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-log {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 200px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
|
background: #0b0e15;
|
||||||
|
color: white;
|
||||||
|
border-top: solid 1px #6e6e6e;
|
||||||
|
font-family: monospace;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-container {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-log {
|
||||||
|
background: #273047;
|
||||||
|
padding: 4px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sensors-log {
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-data-logs {
|
||||||
|
height: 100%;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target-guest {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target-guest-inputs {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
1169
iframe.html
1169
iframe.html
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user