コミットを比較
2 コミット
d2a09f4830
...
e77c52054b
作成者 | SHA1 | 日付 |
---|---|---|
n9k | e77c52054b | |
n9k | b03a74b586 |
|
@ -45,12 +45,13 @@ async def nojs_chat_redirect(user):
|
||||||
@with_user_from(request)
|
@with_user_from(request)
|
||||||
async def nojs_users(user):
|
async def nojs_users(user):
|
||||||
users_by_presence = get_users_by_presence()
|
users_by_presence = get_users_by_presence()
|
||||||
return await render_template(
|
return await render_template_with_etag(
|
||||||
'nojs_users.html',
|
'nojs_users.html',
|
||||||
user=user,
|
user=user,
|
||||||
get_default_name=get_default_name,
|
get_default_name=get_default_name,
|
||||||
users_watching=users_by_presence[Presence.WATCHING],
|
users_watching=users_by_presence[Presence.WATCHING],
|
||||||
users_notwatching=users_by_presence[Presence.NOTWATCHING],
|
users_notwatching=users_by_presence[Presence.NOTWATCHING],
|
||||||
|
timeout=CONFIG['THRESHOLD_NOJS_CHAT_TIMEOUT'],
|
||||||
)
|
)
|
||||||
|
|
||||||
@current_app.route('/chat/form.html')
|
@current_app.route('/chat/form.html')
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* token */
|
/* token */
|
||||||
const token = document.body.dataset.token;
|
const TOKEN = document.body.dataset.token;
|
||||||
|
const TOKEN_HASH = document.body.dataset.token_hash;
|
||||||
|
|
||||||
/* insert js-only markup */
|
/* insert js-only markup */
|
||||||
const jsmarkup_style_color = '<style id="style-color"></style>'
|
const jsmarkup_style_color = '<style id="style-color"></style>'
|
||||||
|
@ -11,6 +12,17 @@ const jsmarkup_info_float_viewership = '<div id="info_js__float__viewership"></d
|
||||||
const jsmarkup_info_float_uptime = '<div id="info_js__float__uptime"></div>';
|
const jsmarkup_info_float_uptime = '<div id="info_js__float__uptime"></div>';
|
||||||
const jsmarkup_info_title = '<header id="info_js__title"></header>';
|
const jsmarkup_info_title = '<header id="info_js__title"></header>';
|
||||||
const jsmarkup_chat_messages = '<ol id="chat-messages_js" data-js="true"></ol>';
|
const jsmarkup_chat_messages = '<ol id="chat-messages_js" data-js="true"></ol>';
|
||||||
|
const jsmarkup_chat_users = `\
|
||||||
|
<section id="chat-users_js">
|
||||||
|
<header id="chat-users_js__header"><h4>Users in chat</h4></header>
|
||||||
|
<article id="chat-users_js__main">
|
||||||
|
<h5 id="chat-users-watching-header"></h5>
|
||||||
|
<ul id="chat-users-watching"></ul>
|
||||||
|
<br>
|
||||||
|
<h5 id="chat-users-notwatching-header"></h5>
|
||||||
|
<ul id="chat-users-notwatching"></ul>
|
||||||
|
</article>
|
||||||
|
</section>`;
|
||||||
const jsmarkup_chat_form = `\
|
const jsmarkup_chat_form = `\
|
||||||
<form id="chat-form_js" data-js="true" action="/chat" method="post">
|
<form id="chat-form_js" data-js="true" action="/chat" method="post">
|
||||||
<input id="chat-form_js__nonce" type="hidden" name="nonce" value="">
|
<input id="chat-form_js__nonce" type="hidden" name="nonce" value="">
|
||||||
|
@ -58,6 +70,10 @@ const insert_jsmarkup = () => {jsmarkup_info_float_viewership
|
||||||
const parent = document.getElementById("info_js");
|
const parent = document.getElementById("info_js");
|
||||||
parent.insertAdjacentHTML("beforeend", jsmarkup_info_title);
|
parent.insertAdjacentHTML("beforeend", jsmarkup_info_title);
|
||||||
}
|
}
|
||||||
|
if (document.getElementById("chat-users_js") === null) {
|
||||||
|
const parent = document.getElementById("chat__users");
|
||||||
|
parent.insertAdjacentHTML("beforeend", jsmarkup_chat_users);
|
||||||
|
}
|
||||||
if (document.getElementById("chat-messages_js") === null) {
|
if (document.getElementById("chat-messages_js") === null) {
|
||||||
const parent = document.getElementById("chat__messages");
|
const parent = document.getElementById("chat__messages");
|
||||||
parent.insertAdjacentHTML("beforeend", jsmarkup_chat_messages);
|
parent.insertAdjacentHTML("beforeend", jsmarkup_chat_messages);
|
||||||
|
@ -78,6 +94,10 @@ const info_title = document.getElementById("info_js__title");
|
||||||
const info_viewership = document.getElementById("info_js__float__viewership");
|
const info_viewership = document.getElementById("info_js__float__viewership");
|
||||||
const info_uptime = document.getElementById("info_js__float__uptime");
|
const info_uptime = document.getElementById("info_js__float__uptime");
|
||||||
const chat_messages = document.getElementById("chat-messages_js");
|
const chat_messages = document.getElementById("chat-messages_js");
|
||||||
|
const chat_users_watching = document.getElementById("chat-users-watching");
|
||||||
|
const chat_users_watching_header = document.getElementById("chat-users-watching-header");
|
||||||
|
const chat_users_notwatching = document.getElementById("chat-users-notwatching");
|
||||||
|
const chat_users_notwatching_header = document.getElementById("chat-users-notwatching-header");
|
||||||
|
|
||||||
const create_chat_message = (object) => {
|
const create_chat_message = (object) => {
|
||||||
const user = users[object.token_hash];
|
const user = users[object.token_hash];
|
||||||
|
@ -93,7 +113,7 @@ const create_chat_message = (object) => {
|
||||||
chat_message_time.title = `${object.date} ${object.time_seconds}`;
|
chat_message_time.title = `${object.date} ${object.time_seconds}`;
|
||||||
chat_message_time.innerText = object.time_minutes;
|
chat_message_time.innerText = object.time_minutes;
|
||||||
|
|
||||||
const chat_message_name = create_chat_message_name(user);
|
const chat_message_name = create_chat_name(user);
|
||||||
|
|
||||||
const chat_message_tripcode_nbsp = document.createElement("span");
|
const chat_message_tripcode_nbsp = document.createElement("span");
|
||||||
chat_message_tripcode_nbsp.classList.add("for-tripcode");
|
chat_message_tripcode_nbsp.classList.add("for-tripcode");
|
||||||
|
@ -120,18 +140,18 @@ const create_chat_message = (object) => {
|
||||||
|
|
||||||
return chat_message;
|
return chat_message;
|
||||||
}
|
}
|
||||||
const create_chat_message_name = (user) => {
|
const create_chat_name = (user) => {
|
||||||
const chat_message_name = document.createElement("span");
|
const chat_name = document.createElement("span");
|
||||||
chat_message_name.classList.add("chat-message__name");
|
chat_name.classList.add("chat-name");
|
||||||
chat_message_name.innerText = get_user_name({user});
|
chat_name.innerText = get_user_name({user});
|
||||||
//chat_message_name.dataset.color = user.color; // not working in any browser
|
//chat_message_name.dataset.color = user.color; // not working in any browser
|
||||||
if (!user.broadcaster && user.name === null) {
|
if (!user.broadcaster && user.name === null) {
|
||||||
const chat_message_name_tag = document.createElement("sup");
|
const chat_name_tag = document.createElement("sup");
|
||||||
chat_message_name_tag.classList.add("chat-message__name__tag");
|
chat_name_tag.classList.add("chat-name__tag");
|
||||||
chat_message_name_tag.innerText = user.tag;
|
chat_name_tag.innerText = user.tag;
|
||||||
chat_message_name.insertAdjacentElement("beforeend", chat_message_name_tag);
|
chat_name.insertAdjacentElement("beforeend", chat_name_tag);
|
||||||
}
|
}
|
||||||
return chat_message_name;
|
return chat_name;
|
||||||
}
|
}
|
||||||
const create_and_add_chat_message = (object) => {
|
const create_and_add_chat_message = (object) => {
|
||||||
const chat_message = create_chat_message(object);
|
const chat_message = create_chat_message(object);
|
||||||
|
@ -172,7 +192,7 @@ const update_user_colors = (token_hash=null) => {
|
||||||
token_hashes = token_hash === null ? Object.keys(users) : [token_hash];
|
token_hashes = token_hash === null ? Object.keys(users) : [token_hash];
|
||||||
const {to_delete, to_ignore} = tidy_stylesheet({
|
const {to_delete, to_ignore} = tidy_stylesheet({
|
||||||
stylesheet: stylesheet_color,
|
stylesheet: stylesheet_color,
|
||||||
selector_regex: /\.chat-message\[data-token-hash="([a-z2-7]{26})"\] > \.chat-message__name/,
|
selector_regex: /\[data-token-hash="([a-z2-7]{26})"\] > \.chat-name/,
|
||||||
ignore_condition: (this_token_hash, this_user, css_rule) => {
|
ignore_condition: (this_token_hash, this_user, css_rule) => {
|
||||||
const irrelevant = ignore_other_token_hashes && this_token_hash !== token_hash;
|
const irrelevant = ignore_other_token_hashes && this_token_hash !== token_hash;
|
||||||
const correct_color = equal(css_rule.style.color, this_user.color);
|
const correct_color = equal(css_rule.style.color, this_user.color);
|
||||||
|
@ -184,7 +204,7 @@ const update_user_colors = (token_hash=null) => {
|
||||||
if (!to_ignore.has(this_token_hash)) {
|
if (!to_ignore.has(this_token_hash)) {
|
||||||
const user = users[this_token_hash];
|
const user = users[this_token_hash];
|
||||||
stylesheet_color.insertRule(
|
stylesheet_color.insertRule(
|
||||||
`.chat-message[data-token-hash="${this_token_hash}"] > .chat-message__name { color: ${user.color}; }`,
|
`[data-token-hash="${this_token_hash}"] > .chat-name { color: ${user.color}; }`,
|
||||||
stylesheet_color.cssRules.length,
|
stylesheet_color.cssRules.length,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -204,8 +224,8 @@ const update_user_names = (token_hash=null) => {
|
||||||
const this_token_hash = chat_message.dataset.tokenHash;
|
const this_token_hash = chat_message.dataset.tokenHash;
|
||||||
if (token_hashes.includes(this_token_hash)) {
|
if (token_hashes.includes(this_token_hash)) {
|
||||||
const user = users[this_token_hash];
|
const user = users[this_token_hash];
|
||||||
const chat_message_name = chat_message.querySelector(".chat-message__name");
|
const chat_message_name = chat_message.querySelector(".chat-name");
|
||||||
chat_message_name.innerHTML = create_chat_message_name(user).innerHTML;
|
chat_message_name.innerHTML = create_chat_name(user).innerHTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +350,7 @@ const enable_captcha = (digest) => {
|
||||||
chat_form_captcha_answer.disabled = false;
|
chat_form_captcha_answer.disabled = false;
|
||||||
chat_form_comment.required = false;
|
chat_form_comment.required = false;
|
||||||
chat_form_captcha_image.removeAttribute("src");
|
chat_form_captcha_image.removeAttribute("src");
|
||||||
chat_form_captcha_image.src = `/captcha.jpg?token=${encodeURIComponent(token)}&digest=${encodeURIComponent(digest)}`;
|
chat_form_captcha_image.src = `/captcha.jpg?token=${encodeURIComponent(TOKEN)}&digest=${encodeURIComponent(digest)}`;
|
||||||
chat_form_submit.disabled = false;
|
chat_form_submit.disabled = false;
|
||||||
chat_form.dataset.captcha = "";
|
chat_form.dataset.captcha = "";
|
||||||
}
|
}
|
||||||
|
@ -387,6 +407,61 @@ const set_viewership = (n) => {
|
||||||
info_viewership.innerText = n === null ? "" : `${n} viewers`;
|
info_viewership.innerText = n === null ? "" : `${n} viewers`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const update_users_list = () => {
|
||||||
|
listed_watching = new Set();
|
||||||
|
listed_notwatching = new Set();
|
||||||
|
|
||||||
|
// remove no-longer-known users
|
||||||
|
for (const element of chat_users_watching.querySelectorAll('.chat-user')) {
|
||||||
|
const token_hash = element.dataset.tokenHash;
|
||||||
|
if (!Object.prototype.hasOwnProperty(users, token_hash)) {
|
||||||
|
element.remove();
|
||||||
|
} else {
|
||||||
|
listed_watching.add(token_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const element of chat_users_notwatching.querySelectorAll('.chat-user')) {
|
||||||
|
const token_hash = element.dataset.tokenHash;
|
||||||
|
if (!Object.prototype.hasOwnProperty(users, token_hash)) {
|
||||||
|
element.remove();
|
||||||
|
} else {
|
||||||
|
listed_notwatching.add(token_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add remaining watching/non-watching users
|
||||||
|
const insert = (user, token_hash, is_you, chat_users_sublist) => {
|
||||||
|
const chat_user_name = create_chat_name(user);
|
||||||
|
const chat_user = document.createElement("li");
|
||||||
|
chat_user.classList.add("chat-user");
|
||||||
|
chat_user.dataset.tokenHash = token_hash;
|
||||||
|
chat_user.insertAdjacentElement("beforeend", chat_user_name);
|
||||||
|
if (is_you) {
|
||||||
|
const you = document.createElement("span");
|
||||||
|
you.innerText = " (You)";
|
||||||
|
chat_user.insertAdjacentElement("beforeend", you);
|
||||||
|
}
|
||||||
|
chat_users_sublist.insertAdjacentElement("beforeend", chat_user);
|
||||||
|
}
|
||||||
|
let watching = 0, notwatching = 0;
|
||||||
|
for (const token_hash of Object.keys(users)) {
|
||||||
|
const user = users[token_hash];
|
||||||
|
const is_you = token_hash === TOKEN_HASH;
|
||||||
|
if (user.watching === true && !listed_watching.has(token_hash)) {
|
||||||
|
insert(user, token_hash, is_you, chat_users_watching);
|
||||||
|
watching++;
|
||||||
|
}
|
||||||
|
if (user.watching === false && !listed_notwatching.has(token_hash)) {
|
||||||
|
insert(user, token_hash, is_you, chat_users_notwatching);
|
||||||
|
notwatching++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show correct numbers
|
||||||
|
chat_users_watching_header.innerText = `Watching (${watching})`;
|
||||||
|
chat_users_notwatching_header.innerText = `Not watching (${notwatching})`;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -435,11 +510,12 @@ const on_websocket_message = (event) => {
|
||||||
default_name = receipt.default;
|
default_name = receipt.default;
|
||||||
max_chat_scrollback = receipt.scrollback;
|
max_chat_scrollback = receipt.scrollback;
|
||||||
|
|
||||||
// appearances
|
// update users
|
||||||
users = receipt.users;
|
users = receipt.users;
|
||||||
update_user_names();
|
update_user_names();
|
||||||
update_user_colors();
|
update_user_colors();
|
||||||
update_user_tripcodes();
|
update_user_tripcodes();
|
||||||
|
update_users_list()
|
||||||
|
|
||||||
// insert new messages
|
// insert new messages
|
||||||
const last = chat_messages.children.length == 0 ? null : chat_messages.children[chat_messages.children.length - 1];
|
const last = chat_messages.children.length == 0 ? null : chat_messages.children[chat_messages.children.length - 1];
|
||||||
|
@ -499,6 +575,7 @@ const on_websocket_message = (event) => {
|
||||||
update_user_names();
|
update_user_names();
|
||||||
update_user_colors();
|
update_user_colors();
|
||||||
update_user_tripcodes();
|
update_user_tripcodes();
|
||||||
|
update_users_list()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "rem-users":
|
case "rem-users":
|
||||||
|
@ -508,6 +585,7 @@ const on_websocket_message = (event) => {
|
||||||
}
|
}
|
||||||
update_user_colors();
|
update_user_colors();
|
||||||
update_user_tripcodes();
|
update_user_tripcodes();
|
||||||
|
update_users_list()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "captcha":
|
case "captcha":
|
||||||
|
@ -530,7 +608,7 @@ const connect_websocket = () => {
|
||||||
}
|
}
|
||||||
chat_live_ball.style.borderColor = "gold";
|
chat_live_ball.style.borderColor = "gold";
|
||||||
chat_live_status.innerHTML = "<span data-verbose='false'>Waiting...</span> <span data-verbose='true'>Connecting to chat...</span>";
|
chat_live_status.innerHTML = "<span data-verbose='false'>Waiting...</span> <span data-verbose='true'>Connecting to chat...</span>";
|
||||||
ws = new WebSocket(`ws://${document.domain}:${location.port}/live?token=${encodeURIComponent(token)}`);
|
ws = new WebSocket(`ws://${document.domain}:${location.port}/live?token=${encodeURIComponent(TOKEN)}`);
|
||||||
ws.addEventListener("open", (event) => {
|
ws.addEventListener("open", (event) => {
|
||||||
console.log("websocket open", event);
|
console.log("websocket open", event);
|
||||||
chat_form_submit.disabled = false;
|
chat_form_submit.disabled = false;
|
||||||
|
|
|
@ -181,13 +181,13 @@ noscript {
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
cursor: help;
|
cursor: help;
|
||||||
}
|
}
|
||||||
.chat-message__name {
|
.chat-name {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
/* color: attr("data-color"); */
|
/* color: attr("data-color"); */
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
.chat-message__name__tag {
|
.chat-name__tag {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@ -203,6 +203,40 @@ noscript {
|
||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
#chat__users {
|
||||||
|
background-color: #121214;
|
||||||
|
mask-image: linear-gradient(black calc(100% - 0.625rem), transparent calc(100% - 0.125rem));
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
#chat-users_js {
|
||||||
|
margin-bottom: 0.875rem;
|
||||||
|
}
|
||||||
|
#chat-users_js__header {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background-color: #2c2c30;
|
||||||
|
border-bottom: var(--chat-border);
|
||||||
|
}
|
||||||
|
#chat-users_js__header > h4 {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#chat-users_js__main {
|
||||||
|
margin: 0.5rem 0.75rem;
|
||||||
|
}
|
||||||
|
#chat-users-watching-header,
|
||||||
|
#chat-users-notwatching-header {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#chat-users-watching,
|
||||||
|
#chat-users-notwatching {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.chat-user {
|
||||||
|
line-height: 1.4375;
|
||||||
|
}
|
||||||
#chat-users_nojs {
|
#chat-users_nojs {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
|
||||||
</head>
|
</head>
|
||||||
<body id="both" data-token="{{ user.token }}">
|
<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>
|
<video id="stream" src="{{ url_for('stream', token=user.token) }}" autoplay controls></video>
|
||||||
<article id="info">
|
<article id="info">
|
||||||
<noscript><iframe id="info_nojs" src="{{ url_for('nojs_info', token=user.token) }}" data-js="false"></iframe></noscript>
|
<noscript><iframe id="info_nojs" src="{{ url_for('nojs_info', token=user.token) }}" data-js="false"></iframe></noscript>
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transform: rotate(-180deg);
|
transform: rotate(-180deg);
|
||||||
}
|
}
|
||||||
#chat-timeout {
|
#timeout {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.5rem;
|
top: 0.5rem;
|
||||||
|
@ -41,15 +41,15 @@
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
animation: appear 0s {{ timeout }}s forwards;
|
animation: appear 0s {{ timeout }}s forwards;
|
||||||
}
|
}
|
||||||
#chat-timeout header {
|
#timeout header {
|
||||||
font-size: 20pt;
|
font-size: 20pt;
|
||||||
}
|
}
|
||||||
#chat-timeout-dismiss {
|
#timeout-dismiss {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
width: calc(100% - 1rem);
|
width: calc(100% - 1rem);
|
||||||
}
|
}
|
||||||
#chat-timeout-dismiss > .button {
|
#timeout-dismiss > .button {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -58,12 +58,12 @@
|
||||||
appear 0s {{ timeout }}s forwards,
|
appear 0s {{ timeout }}s forwards,
|
||||||
unskinny 0s {{ timeout }}s forwards;
|
unskinny 0s {{ timeout }}s forwards;
|
||||||
}
|
}
|
||||||
#chat-timeout-alt {
|
#timeout-alt {
|
||||||
padding: 4px 0 2px 0;
|
padding: 4px 0 2px 0;
|
||||||
}
|
}
|
||||||
#notimeout:target + #chat-timeout,
|
#notimeout:target + #timeout,
|
||||||
#notimeout:target ~ #chat-timeout-dismiss,
|
#notimeout:target ~ #timeout-dismiss,
|
||||||
#notimeout:not(:target) ~ #chat-timeout-alt {
|
#notimeout:not(:target) ~ #timeout-alt {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@keyframes appear {
|
@keyframes appear {
|
||||||
|
@ -127,7 +127,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="end"></div>
|
<div id="end"></div>
|
||||||
<div id="notimeout"></div>
|
<div id="notimeout"></div>
|
||||||
<aside id="chat-timeout">
|
<aside id="timeout">
|
||||||
<a class="button" href="{{ url_for('nojs_chat_redirect') }}">
|
<a class="button" href="{{ url_for('nojs_chat_redirect') }}">
|
||||||
<header>Timed out</header>
|
<header>Timed out</header>
|
||||||
<small>Click to refresh</small>
|
<small>Click to refresh</small>
|
||||||
|
@ -146,10 +146,10 @@
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
<aside id="chat-timeout-dismiss">
|
<aside id="timeout-dismiss">
|
||||||
<a class="button" href="#notimeout">Hide timeout notice</a>
|
<a class="button" href="#notimeout">Hide timeout notice</a>
|
||||||
</aside>
|
</aside>
|
||||||
<aside id="chat-timeout-alt">
|
<aside id="timeout-alt">
|
||||||
<a class="button" href="{{ url_for('nojs_chat_redirect') }}">Click to refresh</a>
|
<a class="button" href="{{ url_for('nojs_chat_redirect') }}">Click to refresh</a>
|
||||||
</aside>
|
</aside>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="refresh" content="6">
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0 0 0.875rem;
|
||||||
background: linear-gradient(#121214 calc(100% - 0.625rem), #232327 calc(100% - 0.125rem));
|
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
#header {
|
#header {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background-color: #27272a;
|
background-color: #2c2c30;
|
||||||
border-bottom: 1px solid #4a4a4f;
|
border-bottom: 1px solid #4a4a4f;
|
||||||
}
|
}
|
||||||
#header > h4 {
|
#header > h4 {
|
||||||
|
@ -23,6 +23,39 @@
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
#timeout {
|
||||||
|
height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
animation: appear 0s {{ timeout }}s forwards;
|
||||||
|
}
|
||||||
|
#timeout > a {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #3674bf;
|
||||||
|
border: 4px outset #3584e4;
|
||||||
|
box-shadow: 0 0 5px #3584e4;
|
||||||
|
padding: 1.25ch 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
animation: unskinny 0s {{ timeout }}s forwards;
|
||||||
|
}
|
||||||
|
#timeout header {
|
||||||
|
font-size: 20pt;
|
||||||
|
}
|
||||||
|
@keyframes appear {
|
||||||
|
to {
|
||||||
|
height: auto;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes unskinny {
|
||||||
|
to {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
#main {
|
#main {
|
||||||
margin: 0.5rem 0.75rem;
|
margin: 0.5rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +68,7 @@
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
.user {
|
.user {
|
||||||
line-height: 1.5;
|
line-height: 1.4375;
|
||||||
}
|
}
|
||||||
.user__name {
|
.user__name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -50,6 +83,12 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header id="header"><h4>Users in chat</h4></header>
|
<header id="header"><h4>Users in chat</h4></header>
|
||||||
|
<aside id="timeout">
|
||||||
|
<a href="">
|
||||||
|
<header>Timed out</header>
|
||||||
|
<small>Click to refresh</small>
|
||||||
|
</a>
|
||||||
|
</aside>
|
||||||
<main id="main">
|
<main id="main">
|
||||||
<h5>Watching ({{ users_watching | length }})</h5>
|
<h5>Watching ({{ users_watching | length }})</h5>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
読み込み中…
新しいイシューから参照