Offline screen

このコミットが含まれているのは:
n9k 2022-03-30 08:41:42 +00:00
コミット a7bfab4f26
4個のファイルの変更74行の追加14行の削除

ファイルの表示

@ -5,7 +5,7 @@ from quart import current_app, request, render_template, redirect, url_for, esca
from anonstream.captcha import get_random_captcha_digest_for from anonstream.captcha import get_random_captcha_digest_for
from anonstream.chat import add_chat_message, Rejected from anonstream.chat import add_chat_message, Rejected
from anonstream.stream import get_stream_title, get_stream_uptime_and_viewership from anonstream.stream import is_online, get_stream_title, get_stream_uptime_and_viewership
from anonstream.user import add_state, pop_state, try_change_appearance, update_presence, get_users_by_presence, Presence, verify, deverify, BadCaptcha from anonstream.user import add_state, pop_state, try_change_appearance, update_presence, get_users_by_presence, Presence, verify, deverify, BadCaptcha
from anonstream.routes.wrappers import with_user_from, render_template_with_etag from anonstream.routes.wrappers import with_user_from, render_template_with_etag
from anonstream.helpers.chat import get_scrollback from anonstream.helpers.chat import get_scrollback
@ -24,6 +24,7 @@ async def nojs_stream(user):
'nojs_stream.html', 'nojs_stream.html',
csp=generate_csp(), csp=generate_csp(),
user=user, user=user,
online=is_online(),
) )
@current_app.route('/info.html') @current_app.route('/info.html')

ファイルの表示

@ -11,7 +11,8 @@ const TOKEN_HASH = document.body.dataset.tokenHash;
const CSP = document.body.dataset.csp; const CSP = document.body.dataset.csp;
/* insert js-only markup */ /* insert js-only markup */
const jsmarkup_stream = `<video id="stream_js" src="/stream.mp4?token=${encodeURIComponent(TOKEN)}" autoplay controls></video>` const jsmarkup_stream_video = '<video id="stream__video" autoplay controls></video>'
const jsmarkup_stream_offline = '<header id="stream__offline"><h1>[offline]</h1></header>'
const jsmarkup_info = '<div id="info_js" data-js="true"></div>'; const jsmarkup_info = '<div id="info_js" data-js="true"></div>';
const jsmarkup_info_float = '<aside id="info_js__float"></aside>'; const jsmarkup_info_float = '<aside id="info_js__float"></aside>';
const jsmarkup_info_float_button = '<button id="info_js__float__button">Reload stream</button>'; const jsmarkup_info_float_button = '<button id="info_js__float__button">Reload stream</button>';
@ -83,9 +84,13 @@ const insert_jsmarkup = () => {
style_tripcode_colors.nonce = CSP; style_tripcode_colors.nonce = CSP;
document.head.insertAdjacentElement("beforeend", style_tripcode_colors); document.head.insertAdjacentElement("beforeend", style_tripcode_colors);
} }
if (document.getElementById("stream_js") === null) { if (document.getElementById("stream__video") === null) {
const parent = document.getElementById("stream"); const parent = document.getElementById("stream");
parent.insertAdjacentHTML("beforeend", jsmarkup_stream); parent.insertAdjacentHTML("beforeend", jsmarkup_stream_video);
}
if (document.getElementById("stream__offline") === null) {
const parent = document.getElementById("stream");
parent.insertAdjacentHTML("beforeend", jsmarkup_stream_offline);
} }
if (document.getElementById("info_js") === null) { if (document.getElementById("info_js") === null) {
const parent = document.getElementById("info"); const parent = document.getElementById("info");
@ -568,6 +573,12 @@ const update_users_list = () => {
chat_users_notwatching_header.innerText = `Not watching (${notwatching})`; chat_users_notwatching_header.innerText = `Not watching (${notwatching})`;
} }
const show_offline_screen = () => {
video.removeAttribute("src");
video.load();
stream.dataset.offline = "";
}
const on_websocket_message = (event) => { const on_websocket_message = (event) => {
//console.log("websocket message", event); //console.log("websocket message", event);
const receipt = JSON.parse(event.data); const receipt = JSON.parse(event.data);
@ -664,7 +675,7 @@ const on_websocket_message = (event) => {
} }
// stream reload button // stream reload button
if (stats === null || stream.networkState === stream.NETWORK_LOADING) { if (stats === null || video.networkState === video.NETWORK_LOADING) {
info_button.removeAttribute("data-visible"); info_button.removeAttribute("data-visible");
} else { } else {
info_button.dataset.visible = ""; info_button.dataset.visible = "";
@ -819,18 +830,26 @@ const connect_websocket = () => {
connect_websocket(); connect_websocket();
/* stream reload button */ /* stream reload button */
const stream = document.getElementById("stream_js"); const video = document.getElementById("stream__video");
const info_button = document.getElementById("info_js__float__button"); const info_button = document.getElementById("info_js__float__button");
info_button.addEventListener("click", (event) => { info_button.addEventListener("click", (event) => {
stream.load(); stream.removeAttribute("data-offline");
video.src = `/stream.mp4?token=${encodeURIComponent(TOKEN)}`;
video.load();
info_button.removeAttribute("data-visible"); info_button.removeAttribute("data-visible");
}); });
stream.addEventListener("error", (event) => { video.addEventListener("error", (event) => {
if (video.error !== null && video.error.message === "404: Not Found") {
show_offline_screen();
}
if (stats !== null) { if (stats !== null) {
info_button.dataset.visible = ""; info_button.dataset.visible = "";
} }
}); });
/* load stream */
video.src = `/stream.mp4?token=${encodeURIComponent(TOKEN)}`;
/* override js-only chat form */ /* override js-only chat form */
const chat_form_nonce = document.getElementById("chat-form_js__nonce"); const chat_form_nonce = document.getElementById("chat-form_js__nonce");
const chat_form_comment = document.getElementById("chat-form_js__comment"); const chat_form_comment = document.getElementById("chat-form_js__comment");

ファイルの表示

@ -56,11 +56,30 @@ noscript {
#stream { #stream {
background: black; background: black;
grid-area: stream; grid-area: stream;
position: relative;
} }
#stream_js { #stream__video {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
#stream__offline {
position: absolute;
top: 0;
width: 100%;
height: 100%;
text-align: center;
display: grid;
align-content: center;
font-size: 20pt;
background-color: black;
user-select: none;
}
#stream__offline > h1 {
margin: 0;
}
#stream:not([data-offline]) > #stream__offline {
display: none;
}
#stream_nojs { #stream_nojs {
height: 100%; height: 100%;
} }

ファイルの表示

@ -16,14 +16,35 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
color: #ddd;
font-family: sans-serif;
} }
#stream { {% if online %}
width: 100%; #video {
height: 100%; width: 100%;
} height: 100%;
}
{% else %}
#offline {
width: 100%;
height: 100%;
text-align: center;
display: grid;
align-content: center;
font-size: 20pt;
user-select: none;
}
#offline > h1 {
margin: 0;
}
{% endif %}
</style> </style>
</head> </head>
<body> <body>
<video id="stream" src="{{ url_for('stream', token=user.token) }}" autoplay controls></video> {% if online %}
<video id="video" src="{{ url_for('stream', token=user.token) }}" autoplay controls></video>
{% else %}
<header id="offline"><h1>[offline]</h1></header>
{% endif %}
</body> </body>
</html> </html>