TheBird

Post.jsx

2.7 kB · jsx · 83 lines

1import { useEffect, useState } from "react";2import { Breadcrumbs } from "../components/Breadcrumbs.jsx";3import { Icon } from "../components/Icon.jsx";4import { FEED_ROUTE, postManifest, postMaster, postPoster, postRoute, postVideo } from "../lib/feed.ts";56const seconds = (n) => `${Number(n).toFixed(1)}s`;78export function Post({ post, prev, next }) {9  const [text, setText] = useState("");1011  useEffect(() => {12    let live = true;13    void fetch(postManifest(post.name))14      .then((reply) => (reply.ok ? reply.json() : null))15      .then((manifest) => {16        if (!live || !manifest) return;17        const { steps, ...rest } = manifest;18        setText(JSON.stringify(rest, null, 2));19      })20      .catch(() => {});21    return () => {22      live = false;23    };24  }, [post.name]);2526  return (27    <div className="wrap">28      <Breadcrumbs trail={[{ name: "Feed", href: FEED_ROUTE }, { name: post.name }]} />29      <article className="play product">30        <div className="left">31          <div className="frame">32            <video controls loop playsInline preload="metadata" poster={postPoster(post.name)} width={post.size || 1080} height={post.size || 1080}>33              <source src={postVideo(post.name)} type="video/mp4" />34            </video>35          </div>36        </div>37        <div className="side">38          <h1 className="mono">{post.name}</h1>39          {post.story ? <p className="story">{post.story}</p> : null}40          <dl className="meta">41            <div>42              <dt>Seed</dt>43              <dd>{post.seed}</dd>44            </div>45            <div>46              <dt>Duration</dt>47              <dd>{seconds(post.duration)}</dd>48            </div>49            <div>50              <dt>Canvas</dt>51              <dd>{post.canvas}</dd>52            </div>53            <div>54              <dt>Frames</dt>55              <dd>{post.frames}</dd>56            </div>57          </dl>58          <p className="get">59            <a className="pill go wide" href={postMaster(post.name)} download>60              <Icon name="download" />61              Download 108062            </a>63          </p>64          <p className="get">65            {prev ? (66              <a className="pill" href={postRoute(prev.name)} rel="prev">67                <Icon name="chevron_left" />68                Newer69              </a>70            ) : null}71            {next ? (72              <a className="pill" href={postRoute(next.name)} rel="next">73                Older74                <Icon name="chevron_right" />75              </a>76            ) : null}77          </p>78          <pre className="json">{text || <a href={postManifest(post.name)}>{`${post.name}.json`}</a>}</pre>79        </div>80      </article>81    </div>82  );83}