Convert social and federation profile from Jinja to SX rendering
Add primitives (replace, strip-tags, slice, csrf-token), convert all social blueprint routes and federation profile to SX content builders, delete 12 unused Jinja templates and social_lite layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,13 +2,15 @@
|
||||
|
||||
Lightweight social UI for blog/market/events. Federation keeps the full
|
||||
social hub (timeline, compose, notifications, interactions).
|
||||
|
||||
All rendering uses s-expressions (no Jinja templates).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from quart import Blueprint, request, g, redirect, url_for, abort, render_template, Response
|
||||
from quart import Blueprint, request, g, redirect, url_for, abort, Response
|
||||
|
||||
from shared.services.registry import services
|
||||
|
||||
@@ -77,15 +79,36 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
abort(403, "You need to choose a federation username first")
|
||||
return actor
|
||||
|
||||
async def _render_social_page(content: str, actor=None, title: str = "Social"):
|
||||
"""Render a full social page or OOB response depending on request type."""
|
||||
from shared.browser.app.utils.htmx import is_htmx_request
|
||||
from shared.sx.page import get_template_context
|
||||
from shared.sx.helpers import full_page_sx, oob_page_sx, sx_response
|
||||
from shared.infrastructure.ap_social_sx import (
|
||||
_social_full_headers, _social_oob_headers,
|
||||
)
|
||||
|
||||
tctx = await get_template_context()
|
||||
kw = {"actor": actor}
|
||||
|
||||
if is_htmx_request():
|
||||
oob_headers = _social_oob_headers(tctx, **kw)
|
||||
return sx_response(oob_page_sx(
|
||||
oobs=oob_headers,
|
||||
content=content,
|
||||
))
|
||||
else:
|
||||
header_rows = _social_full_headers(tctx, **kw)
|
||||
return full_page_sx(tctx, header_rows=header_rows, content=content)
|
||||
|
||||
# -- Index ----------------------------------------------------------------
|
||||
|
||||
@bp.get("/")
|
||||
async def index():
|
||||
actor = getattr(g, "_social_actor", None)
|
||||
return await render_template(
|
||||
"social/index.html",
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import social_index_content_sx
|
||||
content = social_index_content_sx(actor)
|
||||
return await _render_social_page(content, actor, title="Social")
|
||||
|
||||
# -- Search ---------------------------------------------------------------
|
||||
|
||||
@@ -103,15 +126,9 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
g._ap_s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"social/search.html",
|
||||
query=query,
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import social_search_content_sx
|
||||
content = social_search_content_sx(query, actors, total, 1, followed_urls, actor)
|
||||
return await _render_social_page(content, actor, title="Search")
|
||||
|
||||
@bp.get("/search/page")
|
||||
async def search_page():
|
||||
@@ -130,15 +147,10 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
g._ap_s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"social/_search_results.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
query=query,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import search_results_sx
|
||||
from shared.sx.helpers import sx_response
|
||||
content = search_results_sx(actors, total, page, query, followed_urls, actor)
|
||||
return sx_response(content)
|
||||
|
||||
# -- Follow / Unfollow ----------------------------------------------------
|
||||
|
||||
@@ -169,7 +181,7 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
return redirect(request.referrer or url_for("ap_social.search"))
|
||||
|
||||
async def _actor_card_response(actor, remote_actor_url, is_followed):
|
||||
"""Re-render a single actor card after follow/unfollow via HTMX."""
|
||||
"""Re-render a single actor card after follow/unfollow."""
|
||||
remote_dto = await services.federation.get_or_fetch_remote_actor(
|
||||
g._ap_s, remote_actor_url,
|
||||
)
|
||||
@@ -181,15 +193,12 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
list_type = "followers"
|
||||
else:
|
||||
list_type = "following"
|
||||
return await render_template(
|
||||
"social/_actor_list_items.html",
|
||||
actors=[remote_dto],
|
||||
total=0,
|
||||
page=1,
|
||||
list_type=list_type,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
from shared.infrastructure.ap_social_sx import actor_list_items_sx
|
||||
from shared.sx.helpers import sx_response
|
||||
content = actor_list_items_sx(
|
||||
[remote_dto], 0, 1, list_type, followed_urls, actor,
|
||||
)
|
||||
return sx_response(content)
|
||||
|
||||
# -- Followers ------------------------------------------------------------
|
||||
|
||||
@@ -203,14 +212,9 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
g._ap_s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"social/followers.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import social_followers_content_sx
|
||||
content = social_followers_content_sx(actors, total, 1, followed_urls, actor)
|
||||
return await _render_social_page(content, actor, title="Followers")
|
||||
|
||||
@bp.get("/followers/page")
|
||||
async def followers_list_page():
|
||||
@@ -223,15 +227,10 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
g._ap_s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"social/_actor_list_items.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
list_type="followers",
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import actor_list_items_sx
|
||||
from shared.sx.helpers import sx_response
|
||||
content = actor_list_items_sx(actors, total, page, "followers", followed_urls, actor)
|
||||
return sx_response(content)
|
||||
|
||||
# -- Following ------------------------------------------------------------
|
||||
|
||||
@@ -241,13 +240,9 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
actors, total = await services.federation.get_following(
|
||||
g._ap_s, actor.preferred_username,
|
||||
)
|
||||
return await render_template(
|
||||
"social/following.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import social_following_content_sx
|
||||
content = social_following_content_sx(actors, total, 1, actor)
|
||||
return await _render_social_page(content, actor, title="Following")
|
||||
|
||||
@bp.get("/following/page")
|
||||
async def following_list_page():
|
||||
@@ -256,15 +251,10 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
actors, total = await services.federation.get_following(
|
||||
g._ap_s, actor.preferred_username, page=page,
|
||||
)
|
||||
return await render_template(
|
||||
"social/_actor_list_items.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
list_type="following",
|
||||
followed_urls=set(),
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import actor_list_items_sx
|
||||
from shared.sx.helpers import sx_response
|
||||
content = actor_list_items_sx(actors, total, page, "following", set(), actor)
|
||||
return sx_response(content)
|
||||
|
||||
# -- Actor timeline -------------------------------------------------------
|
||||
|
||||
@@ -295,13 +285,9 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
is_following = existing is not None
|
||||
return await render_template(
|
||||
"social/actor_timeline.html",
|
||||
remote_actor=remote_dto,
|
||||
items=items,
|
||||
is_following=is_following,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import social_actor_timeline_content_sx
|
||||
content = social_actor_timeline_content_sx(remote_dto, items, is_following, actor)
|
||||
return await _render_social_page(content, actor)
|
||||
|
||||
@bp.get("/actor/<int:id>/timeline")
|
||||
async def actor_timeline_page(id: int):
|
||||
@@ -316,12 +302,9 @@ def create_ap_social_blueprint(app_name: str) -> Blueprint:
|
||||
items = await services.federation.get_actor_timeline(
|
||||
g._ap_s, id, before=before,
|
||||
)
|
||||
return await render_template(
|
||||
"social/_timeline_items.html",
|
||||
items=items,
|
||||
timeline_type="actor",
|
||||
actor_id=id,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.infrastructure.ap_social_sx import timeline_items_sx
|
||||
from shared.sx.helpers import sx_response
|
||||
content = timeline_items_sx(items, "actor", id, actor)
|
||||
return sx_response(content)
|
||||
|
||||
return bp
|
||||
|
||||
Reference in New Issue
Block a user