show-all-overlays #18
@ -26,9 +26,6 @@ final class DiceResource(@Context val sse: Sse) {
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
fun parseCommand(@PathParam("id") id: String, data: RollPayload) {
|
||||
if (!sseBroadcasters.containsKey(id)) {
|
||||
sseBroadcasters[id] = sse.newBroadcaster()
|
||||
}
|
||||
data.roll = data.command.split(" ", "&", "and").filter { it.isNotEmpty() }.map { it.trim() }.toTypedArray<String>()
|
||||
data.room = id.split(":")[0]
|
||||
data.user = id.split(":")[1]
|
||||
@ -41,6 +38,17 @@ final class DiceResource(@Context val sse: Sse) {
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/register")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
fun register(@PathParam("id") id: String, data: Any) {
|
||||
println("id = [${id}], data = [${data}]")
|
||||
sseBroadcasters["register:$id"]?.broadcast(
|
||||
eventBuilder.id((UUID.randomUUID()).toString())
|
||||
.mediaType(MediaType.APPLICATION_JSON_TYPE).data(data).build())
|
||||
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/results")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@ -71,6 +79,16 @@ final class DiceResource(@Context val sse: Sse) {
|
||||
sseBroadcasters[id]?.register(sseEventSink)
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/users")
|
||||
@Produces(MediaType.SERVER_SENT_EVENTS)
|
||||
fun users(@PathParam("id") id: String, @Context sseEventSink: SseEventSink) {
|
||||
if (!sseBroadcasters.containsKey("register:$id")) {
|
||||
sseBroadcasters["register:$id"] = sse.newBroadcaster()
|
||||
}
|
||||
sseBroadcasters["register:$id"]?.register(sseEventSink)
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
data class Result(val name: String, val user: String, val themeColor: String) {}
|
||||
|
||||
|
@ -140,6 +140,70 @@
|
||||
height: 100%;
|
||||
margin: 20px
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
position: relative;
|
||||
padding-left: 100px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
margin-left: 75px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.checkbox:hover input ~ .checkmark {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
/* When the checkbox is checked, add a blue background */
|
||||
.checkbox input:checked ~ .checkmark {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
/* Create the checkmark/indicator (hidden when not checked) */
|
||||
.checkmark:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show the checkmark when checked */
|
||||
.checkbox input:checked ~ .checkmark:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Style the checkmark/indicator */
|
||||
.checkbox .checkmark:after {
|
||||
left: 5px;
|
||||
top: 2px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 3px 3px 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="w3-theme-l1">
|
||||
@ -148,18 +212,26 @@
|
||||
<div class="w3-panel w3-theme-l4 w3-card w3-display-container" style="padding: 25px; text-align: center; margin-bottom: auto;">
|
||||
<label for="name" id="nameLabel">Name </label><input type="text" id="name" style="width: 50%; margin-top: 20px" required onkeyup="start(event)"/><br/>
|
||||
<label for="room" id="roomLabel">Room </label><input type="text" id="room" style="width: 50%" required onkeyup="start(event)"/><br/>
|
||||
<button id="start" onclick="start()" style="align-self: center; margin-top: 20px">Start 🞂</button>
|
||||
<div>
|
||||
<button id="start" onclick="start()" style="align-self: center; margin-top: 20px">Start 🞂</button>
|
||||
<label class="checkbox" id="gm-container">Join as GM
|
||||
<input type="checkbox" id="gm" style="margin-left: 50px">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dice-tower" hidden class="w3-panel w3-theme-l4 w3-card w3-display-container" style="padding: 25px; margin-bottom: auto">
|
||||
<button type="button" class="collapsible" style="color: white; font-weight: bold">Overlay URLs <a>🞃</a></button>
|
||||
|
||||
<div class="content">
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline;">
|
||||
<label for="overlayId">Dice-Overlay <a style="color: red"> (Only open once) </a> </label>
|
||||
<input type="text" readonly id="overlayId" style="flex-grow: 1"/>
|
||||
<button popovertarget="overlay-hint" data-trigger="hover" class="overlayButton">🛈</button>
|
||||
<div id="overlay-urls">
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline;">
|
||||
<label for="overlayId" id="overlayLabel">Dice-Overlay </label>
|
||||
<input type="text" readonly id="overlayId" style="flex-grow: 1"/>
|
||||
<button id="overlay-hint-button" popovertarget="overlay-hint" data-trigger="hover" class="overlayButton">🛈</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline;">
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline;" hidden id="all-results-urls">
|
||||
<label for="resultsId">All-Results-Overlay </label><input type="text" readonly id="resultsId" style="flex-grow: 1"/><button popovertarget="all-results-hint" data-trigger="hover" class="overlayButton">🛈</button>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline;">
|
||||
@ -207,7 +279,7 @@
|
||||
<button popovertarget="command-hint" data-trigger="hover" class="overlayButton">🛈</button>
|
||||
</div>
|
||||
|
||||
<div style="margin: 20px 25px">
|
||||
<div style="margin: 20px 25px" id="all-results">
|
||||
<label for="resultSwitch">Show all results </label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="resultSwitch">
|
||||
@ -244,10 +316,14 @@
|
||||
<div class="w3-panel w3-theme-l4 w3-card w3-display-container" style="padding: 25px; margin-bottom: auto">
|
||||
<h2 style="text-align: center">How-To</h2>
|
||||
<ul>
|
||||
<li>Join a room by entering your character name and the name of the room</li>
|
||||
<li>
|
||||
Join a room by entering your character name and the name of the room.<br/>
|
||||
<strong>If you are a GM, make sure to join the room first or let all other players rejoin to get all Overlay-URLs.</strong>
|
||||
</li>
|
||||
|
||||
<li>Open your Dice-Overlay either in a new Tab or as a browser source in OBS</li>
|
||||
<ul>
|
||||
<li>Only open your Dice-Overlay once!</li>
|
||||
<li style="color: red; font-weight: bold">Only open your Dice-Overlay once!</li>
|
||||
<li>You can configure your Overlay with query parameters (more information at the info element next to the link)</li>
|
||||
</ul>
|
||||
<li>Configure your dice</li>
|
||||
@ -273,6 +349,8 @@
|
||||
return window.location.protocol + '//' + window.location.hostname + (window.location.port?.length > 0 ? ':' + window.location.port : '');
|
||||
}
|
||||
function start(event) {
|
||||
console.log(document.getElementById('gm').checked)
|
||||
|
||||
if((!event || event.keyCode === 13) && document.getElementById('name').value.length > 0 && document.getElementById('room').value.length > 0) {
|
||||
document.getElementById('overlayId').value = url() + '/overlay/' + document.getElementById('room').value + ':' + localStorage.getItem('userId') + '?scale=7&clearAfter=30';
|
||||
document.getElementById('resultsId').value = url() + '/overlay/' + document.getElementById('room').value + '/results';
|
||||
@ -283,10 +361,14 @@
|
||||
document.getElementById('dice-tower').hidden = false;
|
||||
document.getElementById('name').hidden = true;
|
||||
document.getElementById('room').hidden = true;
|
||||
document.getElementById('gm-container').hidden = true;
|
||||
document.getElementById('how-to').hidden = true;
|
||||
document.getElementById('results').hidden = false;
|
||||
document.getElementById('all-results').hidden = !document.getElementById('gm').checked;
|
||||
document.getElementById('all-results-urls').style.display = document.getElementById('gm').checked ? 'fles': 'none';
|
||||
document.getElementById('nameLabel').innerHTML = '<strong style="font-size:x-large;">' + document.getElementById('name').value + '</strong>';
|
||||
document.getElementById('roomLabel').innerHTML = '<strong style="font-size:medium;">' + document.getElementById('room').value + '</strong>';
|
||||
document.getElementById('overlayLabel').innerHTML = 'Dice-Overlay for <strong>' + document.getElementById('name').value + '</strong>';
|
||||
document.title = document.getElementById('name').value + ' - Dice-Tower';
|
||||
|
||||
if (localStorage.getItem(document.getElementById('name').value + "-theme")) {
|
||||
@ -295,6 +377,47 @@
|
||||
if (localStorage.getItem(document.getElementById('name').value + "-themeColor")) {
|
||||
document.getElementById('themeColor').setColor(localStorage.getItem(document.getElementById('name').value + "-themeColor"));
|
||||
}
|
||||
let httpRequest = new XMLHttpRequest();
|
||||
httpRequest.open('POST', url() + '/dice/' + document.getElementById('room').value + '/register')
|
||||
httpRequest.setRequestHeader('Content-Type', 'application/json')
|
||||
httpRequest.send(JSON.stringify({
|
||||
name: document.getElementById('name').value,
|
||||
overlay: document.getElementById('overlayId').value,
|
||||
id: document.getElementById('room').value + ':' + localStorage.getItem('userId')
|
||||
} ))
|
||||
if(document.getElementById('gm').checked) {
|
||||
document.getElementById('resultSwitch').checked = true;
|
||||
document.getElementById('resultFrame').src = document.getElementById('resultsId').value;
|
||||
const evtSource = new EventSource(url() + '/dice/'+ document.getElementById('room').value + '/users');
|
||||
evtSource.addEventListener('message', function (event) {
|
||||
let data = JSON.parse(event.data);
|
||||
if (data.id !== document.getElementById('room').value + ':' + localStorage.getItem('userId')) {
|
||||
let overlays = document.getElementById('overlay-urls');
|
||||
let newOverlay = document.getElementById(data.id) ?? document.createElement('div');
|
||||
newOverlay.replaceChildren(...[]);
|
||||
newOverlay.id = data.id;
|
||||
newOverlay.style.display = "flex";
|
||||
newOverlay.style.flexDirection = "row";
|
||||
newOverlay.style.justifyContent = "space-between";
|
||||
newOverlay.style.alignItems = "baseline";
|
||||
let newLabel = document.createElement('label');
|
||||
newLabel.for = data.id + 'url';
|
||||
newLabel.innerHTML = "Dice-Overlay for <strong>" + data.name + "</strong>";
|
||||
let newInput = document.createElement('input');
|
||||
newInput.type = "text";
|
||||
newInput.readOnly = true;
|
||||
newInput.id = data.id + 'url';
|
||||
newInput.style.flexGrow = '1';
|
||||
newInput.value = data.overlay;
|
||||
let hint = document.getElementById('overlay-hint-button').cloneNode(true);
|
||||
newOverlay.appendChild(newLabel);
|
||||
newOverlay.appendChild(newInput);
|
||||
newOverlay.appendChild(hint);
|
||||
overlays.appendChild(newOverlay);
|
||||
}
|
||||
showPopover();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,18 +460,22 @@
|
||||
});
|
||||
}
|
||||
|
||||
const popover = document.querySelectorAll("[popovertarget][data-trigger='hover']");
|
||||
function showPopover() {
|
||||
const popover = document.querySelectorAll("[popovertarget][data-trigger='hover']");
|
||||
|
||||
popover.forEach((e) => {
|
||||
const target = document.querySelector("#" + e.getAttribute("popovertarget"));
|
||||
e.addEventListener("mouseover",()=>{
|
||||
target.showPopover();
|
||||
});
|
||||
popover.forEach((e) => {
|
||||
const target = document.querySelector("#" + e.getAttribute("popovertarget"));
|
||||
e.addEventListener("mouseover",()=>{
|
||||
target.showPopover();
|
||||
});
|
||||
|
||||
e.addEventListener("mouseout",()=>{
|
||||
target.hidePopover();
|
||||
e.addEventListener("mouseout",()=>{
|
||||
target.hidePopover();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
showPopover();
|
||||
|
||||
document.getElementById('resultSwitch').addEventListener('change', function() {
|
||||
if (!this.checked) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user