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}