Merge branch 'main' of lokilocker.com:SomeGuy/sessioncommunities.online

dev
mdPlusPlus 2 years ago
commit cef10a3a57

@ -16,4 +16,6 @@
// do not report warnings (timeouts, SSL/TLS errors) // do not report warnings (timeouts, SSL/TLS errors)
error_reporting(E_ALL & ~E_WARNING); error_reporting(E_ALL & ~E_WARNING);
date_default_timezone_set('UTC');
?> ?>

@ -6,7 +6,7 @@ export const dom = {
tbl_communities: () => document.getElementById("tbl_communities"), tbl_communities: () => document.getElementById("tbl_communities"),
last_checked: () => document.getElementById("last_checked_value"), last_checked: () => document.getElementById("last_checked_value"),
qr_modal: (communityID) => document.getElementById(`modal_${communityID}`), qr_modal: (communityID) => document.getElementById(`modal_${communityID}`),
join_urls: () => document.getElementsByClassName("td_join_url"), join_urls: () => document.getElementsByClassName("join_url_container"),
servers_hidden: () => document.getElementById("servers_hidden"), servers_hidden: () => document.getElementById("servers_hidden"),
snackbar: () => document.getElementById("copy-snackbar") snackbar: () => document.getElementById("copy-snackbar")
} }
@ -57,3 +57,29 @@ export function columnIsNumeric(column) {
].includes(column); ].includes(column);
} }
/**
* Creates an element, and adds attributes and elements to it.
* @param {string} tag - HTML Tag name.
* @param {Object|HTMLElement} args - Array of child elements, may start with props.
* @returns {HTMLElement}
*/
function createElement(tag, ...args) {
const element = document.createElement(tag);
if (args.length === 0) return element;
const propsCandidate = args[0];
if (typeof propsCandidate !== "string" && !(propsCandidate instanceof Element)) {
// args[0] is not child element or text node
// must be props object
Object.assign(element, propsCandidate);
args.shift();
}
element.append(...args);
return element;
}
export const element = new Proxy({}, {
get(_, key) {
return (...args) => createElement(key, ...args)
}
});

@ -17,7 +17,7 @@
import { import {
dom, COLUMN, COLUMN_LITERAL, COMPARISON, ATTRIBUTES, dom, COLUMN, COLUMN_LITERAL, COMPARISON, ATTRIBUTES,
columnAscendingByDefault, columnIsSortable, columnNeedsCasefold, columnAscendingByDefault, columnIsSortable, columnNeedsCasefold,
columnIsNumeric columnIsNumeric, element
} from './js/constants.js'; } from './js/constants.js';
// Hidden communities for transparency. // Hidden communities for transparency.
@ -50,12 +50,13 @@ const filteredCommunities = {
// This can be achieved with `text-overflow: ellipsis` instead // This can be achieved with `text-overflow: ellipsis` instead
// and generated entirely server-side. // and generated entirely server-side.
const transformJoinURL = (join_link) => const transformJoinURL = (join_link) => {
`${join_link.substring(0, 31)}... return element.button({
<button class="copy_button" onclick="copyToClipboard('${join_link}')"> textContent: "Copy",
Copy className: "copy_button",
</button> onclick: () => copyToClipboard(join_link)
`.trim(); });
}
function onLoad(timestamp) { function onLoad(timestamp) {
setLastChecked(timestamp); setLastChecked(timestamp);
@ -78,7 +79,7 @@ function createJoinLinkButtons() {
Array.from(join_URLs).forEach((td_url) => { Array.from(join_URLs).forEach((td_url) => {
const a_href = td_url.querySelector('a'); // get first (only) <a> element const a_href = td_url.querySelector('a'); // get first (only) <a> element
const join_link = a_href.getAttribute("href"); // get link const join_link = a_href.getAttribute("href"); // get link
td_url.innerHTML = transformJoinURL(join_link); // add interactive content td_url.append(transformJoinURL(join_link)); // add interactive content
}); });
} }
@ -131,7 +132,7 @@ function setLastChecked(last_checked) {
const time_passed_in_minutes = const time_passed_in_minutes =
Math.floor(time_passed_in_seconds / 60); // time in minutes, rounded down Math.floor(time_passed_in_seconds / 60); // time in minutes, rounded down
const timestamp_element = dom.last_checked(); const timestamp_element = dom.last_checked();
timestamp_element.innerText = `${time_passed_in_minutes} minutes`; timestamp_element.innerText = `${time_passed_in_minutes} minutes ago`;
} }
/** /**
@ -279,6 +280,9 @@ function sortTable(column) {
setSortState(table, { ascending, column }); setSortState(table, { ascending, column });
} }
// html.js for styling purposes
window.document.documentElement.classList.add("js");
// Crude way to export from module script due to inline event handlers. // Crude way to export from module script due to inline event handlers.
// Ideally, all handlers would be attached from JS via addEventListener. // Ideally, all handlers would be attached from JS via addEventListener.
Object.assign(window, { Object.assign(window, {

@ -1,60 +1,98 @@
html {
font-size: clamp(10px, 2vw, 18px);
}
html.js .noscript {
display: none;
}
/* Dead style */
html:not(.js) .js-only {
display: none;
}
header { header {
display: flex; display: flex;
direction: row; direction: row;
/* Push items as far apart as possible */ /* Push items as far apart as possible */
justify-content: space-between; justify-content: space-between;
} }
#headline { #headline {
text-align: center; text-align: center;
flex-grow: 1; flex-grow: 1;
} }
#tbl_communities { width:100%; } #tbl_communities { width:100%; }
#th_identifier { width:9%; } /* Hide the identifier column before removal. */
.td_identifier { font-family: monospace; } #th_identifier { display: none; }
#th_name { width:13%; } .td_identifier { display: none; font-family: monospace; }
#th_language { width:0% }
.td_language:empty::after {
content: "\2753";
}
#th_description { } #th_description { }
.td_description { .td_description {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: display: -webkit-box;
-webkit-box; -webkit-box-orient: vertical;
-webkit-box-orient: vertical; -webkit-line-clamp: 3;
-webkit-line-clamp: 3;
} }
#th_users { width:0% }
.td_users { text-align: right; } .td_users { text-align: right; }
#th_preview { max-width:5%; }
.td_preview { text-align: center; } .td_preview { text-align: center; }
#th_qr { width:0%; }
#th_join_url { width:15%; }
.td_join_url { .td_join_url {
font-family: monospace; font-family: monospace;
white-space: nowrap; white-space: nowrap;
font-size: .8em;
} }
.copy_button { } .join_url {
/* Apply margin against copy button or link. */
/* URL now guaranteed to have interactive element to right when present. */
margin-right: 1em;
}
@media (max-width: 950px) {
/* Only current width breakpoint; */
/* Would follow w4 and precede w6. */
.show-from-w5 {
display: none;
}
}
.join_url_container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.copy_button { font-size: inherit }
footer { footer {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 100%; width: 100%;
text-align: center; text-align: center;
} }
footer p { footer p {
width: 75%; width: 75%;
margin: .5em; margin: .5em;
text-align: center; text-align: center;
} }
footer nav a { footer nav a {
margin: 0 .5ch; display: inline-block;
margin: .25em;
white-space: nowrap;
} }
/* <Colors> */ /* <Colors> */
@ -73,8 +111,8 @@ footer nav a {
display: inline-block; display: inline-block;
font-family: monospace; font-family: monospace;
border-radius: 4px; border-radius: 4px;
padding: .25em .05em;
width: 6ch; width: 6ch;
line-height: 22px;
text-align: center; text-align: center;
} }
.protocol-http { background-color:lightgray } .protocol-http { background-color:lightgray }
@ -170,3 +208,4 @@ footer nav a {
from {bottom: 30px; opacity: 1;} from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;} to {bottom: 0; opacity: 0;}
} }

@ -18,6 +18,12 @@
return count($servers); return count($servers);
} }
function truncate($url, $len) {
return (strlen($url) > $len + 3)
? substr($url, 0, $len).'...'
: $string;
}
/* /*
* Helper function for reduce_servers * Helper function for reduce_servers
*/ */

@ -1,2 +1,3 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/svg+xml" href="favicon.svg" sizes="any"> <link rel="icon" type="image/svg+xml" href="favicon.svg" sizes="any">

@ -53,27 +53,29 @@
// file_exists($QR_CODES) or mkdir($QR_CODES, 0700); // @Deprecated // file_exists($QR_CODES) or mkdir($QR_CODES, 0700); // @Deprecated
?> ?>
<div id="modal-container">
<?php foreach ($rooms as $id => $room): ?> <?php foreach ($rooms as $id => $room): ?>
<div id="modal_<?=$id?>" class="qr-code-modal"> <div id="modal_<?=$id?>" class="qr-code-modal">
<div class="qr-code-modal-content"> <div class="qr-code-modal-content">
<span class="qr-code-modal-close" onclick='hideQRModal("<?=$id?>")'> <span class="qr-code-modal-close" onclick='hideQRModal("<?=$id?>")'>
&times; &times;
</span> </span>
<!-- <!--
<img <img
src="data:image/png;base64,<?=base64_qr_code($id, $room->join_link)?>" src="data:image/png;base64,<?=base64_qr_code($id, $room->join_link)?>"
alt="Community join link encoded as QR code" alt="Community join link encoded as QR code"
class="qr-code" class="qr-code"
loading="lazy" loading="lazy"
> >
--> -->
<img <img
src="<?=room_qr_code_native($room->join_link)?>" src="<?=room_qr_code_native($room->join_link)?>"
alt="Community join link encoded as QR code" alt="Community join link encoded as QR code"
class="qr-code" class="qr-code"
loading="lazy" loading="lazy"
referrerpolicy="no-referrer" referrerpolicy="no-referrer"
> >
</div>
</div> </div>
</div>
<?php endforeach; ?> <?php endforeach; ?>
</div>

@ -1,4 +1,6 @@
<?php <?php
require_once "$PROJECT_ROOT/php/utils/server-utils.php";
// Once handlers are attached in JS, this check ceases to be useful. // Once handlers are attached in JS, this check ceases to be useful.
function column_sortable($id) { function column_sortable($id) {
return $id != "qr"; return $id != "qr";
@ -37,10 +39,8 @@
<td class="td_identifier"><?=$id?></td> <td class="td_identifier"><?=$id?></td>
<td class="td_language"><?=$room->language?></td> <td class="td_language"><?=$room->language?></td>
<td class="td_name"><?=$room->name?></td> <td class="td_name"><?=$room->name?></td>
<td class="td_description"> <td class="td_description"
<?=$room->description?> ><?=$room->description?></td>
</td>
<td class="td_users"><?=$room->active_users?></td> <td class="td_users"><?=$room->active_users?></td>
<td class="td_preview"> <td class="td_preview">
<a href="<?=$room->preview_link?>" target="_blank" rel="noopener noreferrer"> <a href="<?=$room->preview_link?>" target="_blank" rel="noopener noreferrer">
@ -61,10 +61,12 @@
> >
</td> </td>
<td class="td_join_url"> <td class="td_join_url">
<a href="<?=$room->join_link?>"> <div class="join_url_container">
<?=$room->join_link?> <a class="join_url show-from-w5" title="<?=$room->join_link?>"
><?=truncate($room->join_link, 32)?></a>
</a> <a class="noscript" href="<?=$room->join_link?>"
>Copy link</a>
</div>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>

@ -42,7 +42,9 @@
<span id="servers_hidden">(None hidden as JS is off)</span> <span id="servers_hidden">(None hidden as JS is off)</span>
</p> </p>
<p id="last_checked"> <p id="last_checked">
Last checked <span id="last_checked_value"></span> ago. Last checked <span id="last_checked_value">
<?=date("Y-m-d H:i:s", $timestamp)?> (UTC)
</span>.
</p> </p>
<p id="disclaimer"> <p id="disclaimer">
This site is not affiliated with This site is not affiliated with
@ -55,13 +57,11 @@
objectionable or illegal content, but objectionable or illegal content, but
you should still proceed with caution. you should still proceed with caution.
</p> </p>
<noscript> <p class="noscript">
<p> This site works fine without JavaScript.
This site works fine without JavaScript. However, some interactive features are
However, some interactive features are only available with JS enabled.
only available with JS enabled. </p>
</p>
</noscript>
<nav> <nav>
<a <a
href="https://lokilocker.com/Mods/Session-Groups/wiki/Session-Closed-Groups" href="https://lokilocker.com/Mods/Session-Groups/wiki/Session-Closed-Groups"

Loading…
Cancel
Save