Added functional code before manifest and CSS

The JS-part of this demo is now functional to the point where a Monkeydo manifest can be played on the different windows. CSS styling and an actual manifest will still have to be created.
This commit is contained in:
Victor Westerlund 2021-10-18 13:14:39 +02:00
parent cad5e2fb27
commit 3ef9e82d79
5 changed files with 90 additions and 72 deletions

View file

@ -1,87 +1,36 @@
import { default as PlayerWindow } from "./PlayerWindow.mjs";
import { default as Monkeydo } from "./monkeydo/Monkeydo.mjs";
const windowPositions = {
"#lyrics": {
width: window.innerWidth / 2,
height: window.innerHeight,
top: 0,
left: 0
},
"#credits": {
width: window.innerWidth / 2,
height: window.innerHeight / 2,
top: 0,
left: window.innerWidth / 2
},
"#art": {
width: window.innerWidth / 2,
height: window.innerHeight / 2,
top: window.innerHeight / 2,
left: window.innerWidth / 2
}
}
class PlayerWindow {
constructor(name) {
this.features = {
menubar: false,
location: false,
resizable: false,
scrollbar: false,
status: false
}
this.url = new URL(window.location.href + "player");
this.url.hash = name;
Object.assign(this.features,windowPositions[this.url.hash]);
}
windowFeatures() {
let output = [];
for(let [key,value] of Object.entries(this.features)) {
if(typeof key === "boolean") {
value = value ? "yes" : "no";
}
output.push(`${key}=${value}`);
}
return output.join(",");
}
open() {
const features = this.windowFeatures();
const open = window.open(this.url.toString(),this.url.hash,features);
if(!open) {
const channel = new BroadcastChannel(this.url.hash);
channel.postMessage(["WINDOW_ERROR",[this.url.hash,"BLOCKED"]]);
}
}
}
export default class WindowManager {
constructor() {
const self = this;
// Bi-directional communcation to player windows
this.channels = {
lyrics: new BroadcastChannel("#lyrics"),
credits: new BroadcastChannel("#credits"),
art: new BroadcastChannel("#art")
"#lyrics": new BroadcastChannel("#lyrics"),
"#credits": new BroadcastChannel("#credits"),
"#art": new BroadcastChannel("#art")
};
// Monkeydo methods
const methods = {
self: self,
pushText: (target,text) => {
const channels = self.channels[target];
for(const channel of channels) {
channel.postMessage(["PUSH_TEXT",text]);
}
blank: (target) => {
self.channels[target].postMessage(["BLANK",target]);
},
lineFeed: (target) => {
self.channels[target].postMessage(["LINE_FEED"]);
},
textFeed: (text,target = "#lyrics") => {
self.channels[target].postMessage(["TEXT_FEED",text]);
},
drawArt: (index,target = "#art") => {
self.channels[target].postMessage(["DRAW_ART",index]);
}
}
this.player = new Monkeydo(methods);
this.player.loop(-1);
}
playbackFailed(promiseObject = false) {
@ -115,9 +64,9 @@ export default class WindowManager {
// Open player windows and start playback
async play() {
const art = this.spawnPlayer("art");
const credits = this.spawnPlayer("credits");
const lyrics = this.spawnPlayer("lyrics");
const art = this.spawnPlayer("#art");
const credits = this.spawnPlayer("#credits");
const lyrics = this.spawnPlayer("#lyrics");
const timeout = new Promise(resolve => setTimeout(() => resolve("TIMEOUT")),3000);
const windows = await Promise.allSettled([lyrics,credits,art]);
@ -130,6 +79,10 @@ export default class WindowManager {
this.playbackFailed(promiseObject);
}
});
// Load Monkeydo manifest and start playback
const manifest = new URL(window.location.href + "monkeydo.json");
this.player.load(manifest.toString()).then(() => this.player.do());
});
}
}

View file

@ -0,0 +1,61 @@
const windowPositions = {
"#lyrics": {
width: window.innerWidth / 2,
height: window.innerHeight,
top: 0,
left: 0
},
"#credits": {
width: window.innerWidth / 2,
height: window.innerHeight / 2,
top: 0,
left: window.innerWidth / 2
},
"#art": {
width: window.innerWidth / 2,
height: window.innerHeight / 2,
top: window.innerHeight / 2,
left: window.innerWidth / 2
}
}
export default class PlayerWindow {
constructor(name) {
this.features = {
menubar: false,
location: false,
resizable: false,
scrollbar: false,
status: false
}
this.url = new URL(window.location.href + "player");
this.url.hash = name;
// Copy window size rect into windowFeatures
Object.assign(this.features,windowPositions[this.url.hash]);
}
// Convert windowFeatures object into a CSV DOMString
windowFeatures() {
let output = [];
for(let [key,value] of Object.entries(this.features)) {
if(typeof key === "boolean") {
value = value ? "yes" : "no";
}
output.push(`${key}=${value}`);
}
return output.join(",");
}
open() {
const features = this.windowFeatures();
const open = window.open(this.url.toString(),this.url.hash,features);
// Window failed to open (usually due to pop-up blocking), tell the WindowManager about this
if(!open) {
const channel = new BroadcastChannel(this.url.hash);
channel.postMessage(["WINDOW_ERROR",[this.url.hash,"BLOCKED"]]);
}
}
}

View file

@ -51,10 +51,11 @@ class StillAlivePlayer {
message(event) {
const type = event.data[0];
const data = event.data[1];
console.log(event);
switch(type) {
case "LINE_FEED": this.lineFeed(); break;
case "CHAR_FEED": this.textFeed(data); break;
case "TEXT_FEED": this.textFeed(data); break;
case "DRAW_ART": this.drawArt(data); break;
case "BLANK": this.blank(); break;
}

View file

@ -1,4 +1,4 @@
import { default as Player } from "./modules/WindowManager.mjs";
import { default as Player } from "./modules/PlayerManager.mjs";
const play = document.getElementById("play");
const message = document.getElementById("message");

3
monkeydo.json Normal file
View file

@ -0,0 +1,3 @@
{
"tasks": []
}