aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--priv/room.html.eex62
-rw-r--r--priv/static/main.css44
-rw-r--r--priv/static/room/main.js59
3 files changed, 130 insertions, 35 deletions
diff --git a/priv/room.html.eex b/priv/room.html.eex
index 012ec0d..c3ae92e 100644
--- a/priv/room.html.eex
+++ b/priv/room.html.eex
@@ -2,15 +2,16 @@
<%
import Mediasync.Constants
-{video_info, websocket_path, state_url, home_button_url} = if in_discord_activity? do
+{video_info, websocket_path, state_url, home_button_url, show_snap_button?} = if in_discord_activity? do
{
%{video_info | url: "/.proxy/room/#{room_id}/video?#{query_param_discord_activity_inner()}"},
"/.proxy/room/#{room_id}/websocket?#{query_param_discord_activity_inner()}",
"/.proxy/room/#{room_id}/state.json?#{query_param_discord_activity_inner()}",
- "/.proxy/?#{query_param_discord_activity_inner()}"
+ "/.proxy/?#{query_param_discord_activity_inner()}",
+ true
}
else
- {video_info, "/room/#{room_id}/websocket", "/room/#{room_id}/state.json", nil}
+ {video_info, "/room/#{room_id}/websocket", "/room/#{room_id}/state.json", nil, false}
end
%>
<html lang="en">
@@ -27,33 +28,31 @@ end
margin: 0;
}
- @font-face {
- font-family: "FontAwesomeSolid";
- src: url("/static/fontawesome-free-6.6.0-web/webfonts/fa-solid-900.woff2") format("woff2");
+ div#outerContainer {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ height: 100svh;
+ width: 100svw;
}
- .icon-home, .icon-users, .icon-left, .icon-right, .icon-left-right {
- font-family: "FontAwesomeSolid";
+ div#playerContainer {
+ /* Default values; JS will adjust depending on actual aspect ratio */
+ height: 100svh;
+ width: 100svw;
+ /* We should be in the (horizontal) center by default */
+ margin: 0 auto;
}
- .icon-home::before {
- content: "\f015";
+ div#playerContainer:has(#snap-button.icon-right) {
+ /* We should be on the left */
+ margin-left: 0;
}
- .icon-users::before {
- content: "\f0c0";
- }
-
- .icon-left::before {
- content: "\f30a";
- }
-
- .icon-right::before {
- content: "\f30b";
- }
-
- .icon-left-right::before {
- content: "\f337";
+ div#playerContainer:has(#snap-button.icon-left-right) {
+ /* We should be on the right */
+ margin-left: auto;
+ margin-right: 0;
}
#state-button-active::after {
@@ -67,14 +66,18 @@ end
top: 0;
}
</style>
+ <!-- Will be modified by JS -->
+ <style id="extra-styles"></style>
</head>
<body>
- <div id="playerContainer">
- <video-js id="player">
- <source src="<%= Plug.HTML.html_escape(video_info.url) %>"
- type="<%= Plug.HTML.html_escape(video_info.content_type) %>">
- </video-js>
+ <div id="outerContainer">
+ <div id="playerContainer">
+ <video-js id="player">
+ <source src="<%= Plug.HTML.html_escape(video_info.url) %>"
+ type="<%= Plug.HTML.html_escape(video_info.content_type) %>">
+ </video-js>
+ </div>
</div>
<script src="/static/video.js/video.min.js"></script>
<script>
@@ -82,6 +85,7 @@ end
const HOME_BUTTON_URL = <%= if home_button_url, do: ~s("#{home_button_url}"), else: "null" %>;
const STATE_ELEMENT_INITIAL_TEXT = "loading...";
const STATE_URL = "<%= state_url %>";
+ const SHOW_SNAP_BUTTON = <%= show_snap_button? %>;
</script>
<script src="/static/room/main.js"></script>
<script src="/static/room/displayState.js"></script>
diff --git a/priv/static/main.css b/priv/static/main.css
index 85906c6..9841b35 100644
--- a/priv/static/main.css
+++ b/priv/static/main.css
@@ -1,3 +1,13 @@
+:root {
+ box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: inherit;
+}
+
body {
background-color: black;
color: white;
@@ -8,7 +18,35 @@ input {
font-family: inherit;
}
-div#playerContainer {
- width: 100svw;
- height: 100svh;
+@font-face {
+ font-family: "FontAwesomeSolid";
+ src: url("/static/fontawesome-free-6.6.0-web/webfonts/fa-solid-900.woff2") format("woff2");
+}
+
+.icon-home,
+.icon-users,
+.icon-left,
+.icon-right,
+.icon-left-right {
+ font-family: "FontAwesomeSolid";
+}
+
+.icon-home::before {
+ content: "\f015";
+}
+
+.icon-users::before {
+ content: "\f0c0";
+}
+
+.icon-left::before {
+ content: "\f30a";
+}
+
+.icon-right::before {
+ content: "\f30b";
+}
+
+.icon-left-right::before {
+ content: "\f337";
}
diff --git a/priv/static/room/main.js b/priv/static/room/main.js
index 9a0b2ec..8e46f66 100644
--- a/priv/static/room/main.js
+++ b/priv/static/room/main.js
@@ -26,6 +26,21 @@
}
};
+ const setPlayerDimensions = (player) => {
+ document.querySelector("style#extra-styles").textContent = `
+ div#playerContainer {
+ height: 100svh;
+ width: calc(100svh * ${player.videoWidth() / player.videoHeight()});
+ }
+ @media (orientation: portrait) {
+ div#playerContainer {
+ width: 100svw;
+ height: calc(100svw * ${player.videoHeight() / player.videoWidth()});
+ }
+ }
+ `;
+ };
+
const player = videojs("player", {
controls: true,
experimentalSvgIcons: true,
@@ -37,6 +52,14 @@
player.ready(() => {
setControlsEnabled(player, false);
+ if (player.readyState() >= 1) {
+ setPlayerDimensions(player);
+ } else {
+ player.on("loadedmetadata", () => {
+ setPlayerDimensions(player);
+ });
+ }
+
{
let customIconPosition = 1;
const Button = videojs.getComponent("Button");
@@ -52,16 +75,46 @@
}
const stateButton = new Button(player, {
- clickHandler: (event) => {
+ clickHandler: (_) => {
const stateButtonEl = stateButton.el();
- const id = stateButtonEl.getAttribute("id");
- stateButtonEl.setAttribute("id", id ? "" : "state-button-active");
+ stateButtonEl.id = stateButtonEl.id ? "" : "state-button-active";
},
});
stateButton.el().setAttribute("data-text", STATE_ELEMENT_INITIAL_TEXT);
stateButton.addClass("icon-users state-element");
stateButton.controlText("Viewers");
player.controlBar.addChild(stateButton, {}, customIconPosition++);
+
+ if (SHOW_SNAP_BUTTON) {
+ const SNAP_NEXT_L = "icon-left";
+ const SNAP_NEXT_R = "icon-right";
+ const SNAP_NEXT_LR = "icon-left-right";
+ const SNAP_TITLE_L = "Snap Video To Left";
+ const SNAP_TITLE_R = "Snap Video To Right";
+ const SNAP_TITLE_LR = "Snap Video To Center";
+ const snapButton = new Button(player, {
+ clickHandler: (_) => {
+ const snapButtonEl = snapButton.el();
+ if (snapButtonEl.classList.contains(SNAP_NEXT_L)) {
+ snapButtonEl.classList.remove(SNAP_NEXT_L);
+ snapButtonEl.classList.add(SNAP_NEXT_R);
+ snapButtonEl.title = SNAP_TITLE_R;
+ } else if (snapButtonEl.classList.contains(SNAP_NEXT_R)) {
+ snapButtonEl.classList.remove(SNAP_NEXT_R);
+ snapButtonEl.classList.add(SNAP_NEXT_LR);
+ snapButtonEl.title = SNAP_TITLE_LR;
+ } else {
+ snapButtonEl.classList.remove(SNAP_NEXT_LR);
+ snapButtonEl.classList.add(SNAP_NEXT_L);
+ snapButtonEl.title = SNAP_TITLE_L;
+ }
+ },
+ });
+ snapButton.el().id = "snap-button";
+ snapButton.addClass(SNAP_NEXT_L);
+ snapButton.controlText(SNAP_TITLE_L);
+ player.controlBar.addChild(snapButton, {}, customIconPosition++);
+ }
}
const updatePlaybackState = (latestReceivedState, nowMilliseconds) => {