From 5d71b7cf8823581f88ec9228e10d413810de30c9 Mon Sep 17 00:00:00 2001 From: Sam MacKinnon Date: Fri, 5 Aug 2022 03:10:43 -0700 Subject: [PATCH] Refactor and redesign iframe.html --- iframe-examples.js | 326 ++++++++++++ iframe.css | 200 ++++++++ iframe.html | 1169 +++++++++++++++++--------------------------- 3 files changed, 978 insertions(+), 717 deletions(-) create mode 100644 iframe-examples.js create mode 100644 iframe.css diff --git a/iframe-examples.js b/iframe-examples.js new file mode 100644 index 0000000..315e79f --- /dev/null +++ b/iframe-examples.js @@ -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 }), + }, + } +} diff --git a/iframe.css b/iframe.css new file mode 100644 index 0000000..899405a --- /dev/null +++ b/iframe.css @@ -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; +} diff --git a/iframe.html b/iframe.html index b1c0839..10ecde1 100644 --- a/iframe.html +++ b/iframe.html @@ -1,718 +1,453 @@ - - - IFRAME Example - - - - - - - - - -Clean Output -Transparent -Hide Menu -
- -
- + + + IFRAME Example + + + + + + + + + + Clean Output + Transparent + Hide Menu +
+ \ No newline at end of file