Add nojs 'Reload stream' button

The nojs button appears when the stream is online and the user is not watching.
The js button appears when the stream is online and the media element either
(1) is not using the network or (2) fires an error event.
このコミットが含まれているのは:
n9k 2022-03-02 10:13:07 +00:00
コミット 46fce9c393
7個のファイルの変更72行の追加9行の削除

ファイルの表示

@ -3,7 +3,7 @@ from quart import current_app, request, render_template, redirect, url_for, esca
from anonstream.captcha import get_random_captcha_digest_for
from anonstream.chat import add_chat_message, Rejected
from anonstream.stream import get_stream_title, get_stream_uptime_and_viewership
from anonstream.user import add_state, pop_state, try_change_appearance, 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.helpers.chat import get_scrollback
from anonstream.helpers.user import get_default_name
@ -13,9 +13,18 @@ from anonstream.utils.user import concatenate_for_notice
CONFIG = current_app.config
USERS_BY_TOKEN = current_app.users_by_token
@current_app.route('/stream.html')
@with_user_from(request)
async def nojs_stream(user):
return await render_template(
'nojs_stream.html',
user=user,
)
@current_app.route('/info.html')
@with_user_from(request)
async def nojs_info(user):
update_presence(user)
uptime, viewership = get_stream_uptime_and_viewership()
return await render_template(
'nojs_info.html',
@ -23,6 +32,7 @@ async def nojs_info(user):
viewership=viewership,
uptime=uptime,
title=await get_stream_title(),
Presence=Presence,
)
@current_app.route('/chat/messages.html')

ファイルの表示

@ -6,6 +6,7 @@ const TOKEN_HASH = document.body.dataset.tokenHash;
const jsmarkup_style_color = '<style id="style-color"></style>'
const jsmarkup_style_tripcode_display = '<style id="style-tripcode-display"></style>'
const jsmarkup_style_tripcode_colors = '<style id="style-tripcode-colors"></style>'
const jsmarkup_stream = `<video id="stream_js" src="/stream.mp4?token=${encodeURIComponent(TOKEN)}" autoplay controls></video>`
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_button = '<button id="info_js__float__button">Reload stream</button>';
@ -48,6 +49,10 @@ const insert_jsmarkup = () => {jsmarkup_info_float_viewership
const parent = document.head;
parent.insertAdjacentHTML("beforeend", jsmarkup_style_tripcode_colors);
}
if (document.getElementById("stream_js") === null) {
const parent = document.getElementById("stream");
parent.insertAdjacentHTML("beforeend", jsmarkup_stream);
}
if (document.getElementById("info_js") === null) {
const parent = document.getElementById("info");
parent.insertAdjacentHTML("beforeend", jsmarkup_info);
@ -680,7 +685,7 @@ const connect_websocket = () => {
connect_websocket();
/* stream reload button */
const stream = document.getElementById("stream");
const stream = document.getElementById("stream_js");
const info_button = document.getElementById("info_js__float__button");
info_button.addEventListener("click", (event) => {
stream.load();

ファイルの表示

@ -50,10 +50,15 @@ noscript {
#stream {
background: black;
width: 100%;
height: var(--video-height);
grid-area: stream;
}
#stream_js {
width: 100%;
height: 100%;
}
#stream_nojs {
height: 100%;
}
#info {
border-top: var(--main-border);

ファイルの表示

@ -5,7 +5,9 @@
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
</head>
<body id="both" data-token="{{ user.token }}" data-token-hash="{{ user.token_hash }}">
<video id="stream" src="{{ url_for('stream', token=user.token) }}" autoplay controls></video>
<article id="stream">
<noscript><iframe id="stream_nojs" name="stream_nojs" src="{{ url_for('nojs_stream', token=user.token) }}"></iframe></noscript>
</article>
<article id="info">
<noscript><iframe id="info_nojs" src="{{ url_for('nojs_info', token=user.token) }}" data-js="false"></iframe></noscript>
</article>

ファイルの表示

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="12">
<meta http-equiv="refresh" content="6">
<style>
body {
overflow-y: auto;
@ -17,6 +17,10 @@
grid-auto-flow: column;
grid-gap: 2.5ch;
}
#float__form {
display: block;
margin: 0;
}
#float__uptime {
font-variant-numeric: tabular-nums;
}
@ -31,6 +35,12 @@
<body>
{% if uptime is not none %}
<aside id="float">
{% if user.presence != Presence.WATCHING %}
<form id="float__form" action="{{ url_for('nojs_stream') }}" target="stream_nojs">
<input type="hidden" name="token" value="{{ user.token }}">
<input type="submit" value="Reload stream">
</form>
{% endif %}
<div id="float__viewership">{{ viewership }} viewers</div>
<div id="float__uptime">{{ uptime }}</div>
</aside>

23
anonstream/templates/nojs_stream.html ノーマルファイル
ファイルの表示

@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
overflow: hidden;
}
#stream {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<video id="stream" src="{{ url_for('stream', token=user.token) }}" autoplay controls></video>
</body>
</html>

ファイルの表示

@ -155,11 +155,19 @@ def deverify(timestamp, user):
if n_user_messages >= CONFIG['FLOOD_THRESHOLD']:
user['verified'] = False
def _update_presence(timestamp, user):
old, user['presence'] = user['presence'], get_presence(timestamp, user)
if trilean(user['presence']) != trilean(old):
USERS_UPDATE_BUFFER.add(user['token'])
return user['presence']
@with_timestamp
def update_presence(timestamp, user):
return _update_presence(timestamp, user)
def get_users_and_update_presence(timestamp):
for user in USERS:
old, user['presence'] = user['presence'], get_presence(timestamp, user)
if trilean(user['presence']) != trilean(old):
USERS_UPDATE_BUFFER.add(user['token'])
_update_presence(timestamp, user)
yield user
def get_watching_users(timestamp):