Compare commits
3 commits
753cf16e9d
...
51208f43b3
| Author | SHA1 | Date | |
|---|---|---|---|
| 51208f43b3 | |||
| a66207cb9b | |||
| 47ec8dce7b |
4 changed files with 81 additions and 15 deletions
|
|
@ -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
60
cry/static/index.js
Normal 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());
|
||||
12
cry/views.py
12
cry/views.py
|
|
@ -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..."),
|
||||
|
|
|
|||
22
cry/web.py
22
cry/web.py
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue