Compare commits

...

3 commits

Author SHA1 Message Date
51208f43b3 Live times 2024-12-01 08:06:23 -08:00
a66207cb9b Note 2024-12-01 07:15:09 -08:00
47ec8dce7b Note 2024-12-01 07:09:44 -08:00
4 changed files with 81 additions and 15 deletions

View file

@ -21,6 +21,8 @@ events.addEventListener("redirect", (e) => {
window.location = e.data;
});
// NOTE: This was designed for a refresh redesign but I haven't the heart to do
// it yet.
events.addEventListener("progress", (e) => {
// Grab the progress element being referred to.
const parameters = JSON.parse(e.data);

60
cry/static/index.js Normal file
View file

@ -0,0 +1,60 @@
console.log("Hello world!");
function time_ago(time) {
// Much like the python in feed.py
const now = Date.now();
const seconds = Math.round((now - time) / 1000);
// If you *must* have live output (for debugging or something) just
// uncomment here.
// return `${seconds}s`;
if (seconds < 90) {
return `${seconds}s`;
}
const minutes = Math.round(seconds / 60);
if (minutes < 90) {
return `${minutes}m`;
}
const hours = Math.round(minutes / 60);
if (hours < 24) {
return `${hours}h`;
}
const days = Math.round(hours / 24);
if (days <= 7) {
return `${days}d`;
}
const weeks = Math.round(days / 7);
if (weeks < 52) {
return `${weeks}w`;
}
const years = Math.round(weeks / 52);
return `{years}y`
}
function timeAgoTick(selector, format) {
const tags = document.querySelectorAll(selector);
for (const tag of tags) {
const then = Date.parse(tag.getAttribute("datetime"));
const when = time_ago(then);
const formatted = format(when);
// NOTE: I'm being a real dork about this because I am super nervous
// about leaking memory/making the page heaver than it needs to be,
// with a callback every second and all.
const text = tag.firstChild;
if (text.data != formatted) {
text.data = formatted;
}
}
}
function registerTimeCallback() {
setInterval(() => {
timeAgoTick(".time-ago-bare", (a) => a);
timeAgoTick(".time-ago-paren", (a) => `(${a})`);
}, 1000);
}
addEventListener("DOMContentLoaded", () => registerTimeCallback());

View file

@ -41,7 +41,10 @@ def _feed_summary(f: feed.Feed) -> tags.li:
{"class": "feed-summary-timestamp"},
tags.i(
f"Posted ",
time_(entry.time_ago(), datetime=entry.posted_time_iso()),
time_(
{"class": "time-ago-bare", "datetime": entry.posted_time_iso()},
entry.time_ago(),
),
" ago",
),
),
@ -116,8 +119,11 @@ def feed_view(feeds: list[feed.Feed]) -> tags.html:
),
" ",
time_(
{
"class": "time-ago-paren",
"datetime": entry.posted_time_iso(),
},
f"({entry.time_ago()})",
datetime=entry.posted_time_iso(),
),
)
for entry in f.entries
@ -131,6 +137,7 @@ def feed_view(feeds: list[feed.Feed]) -> tags.html:
),
),
),
tags.script({"src": "/index.js"}),
)
assert isinstance(document, tags.html)
return document
@ -188,6 +195,7 @@ def status_view() -> tags.html:
return document
# NOTE: Not in use yet.
def refresh_view(feeds: list[feed.Feed]) -> tags.html:
document = tags.html(
_standard_header("Refreshing Feeds..."),

View file

@ -1,10 +1,8 @@
import asyncio
import contextlib
import dataclasses
import dominate.tags as tags
import functools
import http.server
import io
import pathlib
import time
import traceback
@ -17,6 +15,7 @@ from . import database
from . import feed
from . import views
class DeadlineCondition:
"""A condition variable that allows you to wait with a timeout."""
@ -296,6 +295,7 @@ def refresh_feeds(sink: EventChannel):
REFRESH_TASK: BackgroundTask | None = None
@background_task
def subscribe(sink: EventChannel, url: str):
"""Subscribe to a feed."""
@ -338,9 +338,11 @@ class Handler(http.server.BaseHTTPRequestHandler):
if self.path == "/":
return self.serve_feeds()
elif self.path == "/style.css":
return self.serve_style()
return self.serve_static("style.css", "text/css")
elif self.path == "/event.js":
return self.serve_event_js()
return self.serve_static("event.js", "text/javascript")
elif self.path == "/index.js":
return self.serve_static("index.js", "text/javascript")
elif self.path == "/refresh-status":
return self.serve_status()
elif self.path == "/subscribe-status":
@ -478,16 +480,10 @@ class Handler(http.server.BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(response)
def serve_event_js(self):
def serve_static(self, name: str, content_type: str):
self.write_file(
pathlib.Path(__file__).parent / "static" / "event.js",
content_type="text/javascript",
)
def serve_style(self):
self.write_file(
pathlib.Path(__file__).parent / "static" / "style.css",
content_type="text/css",
pathlib.Path(__file__).parent / "static" / name,
content_type=content_type,
)
def write_file(self, path: pathlib.Path, content_type: str):