diff --git a/cry/views.py b/cry/views.py new file mode 100644 index 0000000..c53833d --- /dev/null +++ b/cry/views.py @@ -0,0 +1,80 @@ +import typing + +import dominate.tags as tags + +from . import feed + +def _standard_header(title: str) -> tags.head: + head = tags.head( + tags.meta(charset="utf8"), + tags.title(title), + tags.link(rel="stylesheet", href="/style.css", type="text/css"), + ) + assert isinstance(head, tags.head) + return head + +def feed_view(feeds: list[feed.Feed]) -> tags.html: + document = tags.html( + _standard_header("Subscribed Feeds"), + tags.h1("Feeds"), + tags.div( + tags.form( + {"method": "post", "action": "/refresh"}, + tags.input_(type="submit", value="Refresh"), + ), + tags.form( + {"method": "post", "action": "/subscribe"}, + tags.label({"for": "url"}, "Feed url:"), + tags.input_(type="url", name="url"), + tags.input_(type="submit", value="Subscribe"), + ), + ( + tags.div( + {"class": "feed"}, + tags.h2(tags.a(f.title, href=f.link, target="_blank")), + ( + tags.ul( + tags.li( + {"class": "entry"}, + tags.a( + entry.title, href=entry.link, target="_blank" + ), + f" ({entry.time_ago()})", + ) + for entry in f.entries + ) + if len(f.entries) > 0 + else tags.i("No entries...") + ), + ) + for f in feeds + ), + ), + ) + assert isinstance(document, tags.html) + return document + +def subscribe_choose_view(candidates: typing.Iterable[tuple[str,str]]) -> tags.html: + document = tags.html( + _standard_header("Choose Feed"), + tags.h1("Choose Feed"), + tags.p("More than one feed was found. Choose the feed to subscribe to."), + tags.table( + tags.caption("Potential feeds"), + tags.thead(tags.tr(tags.th("Title"), tags.th("URL"), tags.th())), + tags.tbody( + tags.form( + {"action": "/subscribe", "method":"post"}, + tags.tr( + tags.td(title), tags.td(url), tags.td( + tags.input_({"type":"hidden", "name":"url", "value":url}), + tags.input_({"type":"submit", "value":"Subscribe"}), + ), + ), + ) + for title, url in candidates + ), + ), + ) + assert isinstance(document, tags.html) + return document diff --git a/cry/web.py b/cry/web.py index aaff074..b8fd033 100644 --- a/cry/web.py +++ b/cry/web.py @@ -1,7 +1,7 @@ import asyncio import contextlib import dataclasses -import dominate.tags as d +import dominate.tags as tags import functools import http.server import io @@ -15,7 +15,7 @@ from typing import Callable, Concatenate, ParamSpec from . import database from . import feed - +from . import views class DeadlineCondition: """A condition variable that allows you to wait with a timeout.""" @@ -296,7 +296,6 @@ def refresh_feeds(sink: EventChannel): REFRESH_TASK: BackgroundTask | None = None - @background_task def subscribe(sink: EventChannel, url: str): """Subscribe to a feed.""" @@ -497,36 +496,7 @@ class Handler(http.server.BaseHTTPRequestHandler): feeds.sort(key=feed.sort_key, reverse=True) - document = d.html() - with document: - with d.head(): - d.meta(charset="utf8") - d.title("Subscribed Feeds") - d.link(rel="stylesheet", href="/style.css", type="text/css") - d.h1("Feeds") - with d.div(): - with d.form(method="post", action="/refresh"): - d.input_(type="submit", value="Refresh") - with d.form(method="post", action="/subscribe"): - d.label("Feed url:", fr="url") - d.input_(type="url", name="url") - d.input_(type="submit", value="Subscribe") - - for f in feeds: - with d.div(cls="feed"): - d.h2(d.a(f.title, href=f.link, target="_blank")) - if len(f.entries) > 0: - d.ul( - d.li( - d.a(entry.title, href=entry.link, target="_blank"), - f" ({entry.time_ago()})", - cls="entry", - ) - for entry in f.entries - ) - else: - d.i("No entries...") - + document = views.feed_view(feeds) self.write_html(document.render()) def serve_subscribe_choose(self): @@ -541,47 +511,8 @@ class Handler(http.server.BaseHTTPRequestHandler): self.send_error(400, explain=tb) return - buffer = io.StringIO() - buffer.write( - """ - - - - Choose Feed - - -

Choose Feed

-

More than one feed was found. Choose the feed to subscribe to.

- - - - - - - """ - ) - for title, url in candidates: - buffer.write( - f""" - - - - - - """ - ) - buffer.write( - """ - -
Potential feeds
TitleURL
{title}{url} - - -
- """ - ) - buffer.flush() - - self.write_html(buffer.getvalue()) + document = views.subscribe_choose_view(candidates) + self.write_html(document.render()) def write_html(self, html: str): response = html.encode("utf-8")