a media slot can be framed by dragging and zooming
A photograph is rarely the shape of the slot it goes in, so something decides which part survives. It was a centred crop and no way to change it. Dragging the picture slides the window; the wheel zooms, anchored to the pointer so the thing under the cursor stays under it. Both write the site's own format — `x,y,w,h` in percentages of the ORIGINAL — which is resolution-independent and survives the file being re-encoded. Zooming in is the window getting smaller: w and h shrink together, keeping the slot's shape. Fit is the floor, because you cannot show more of a photograph than there is, and at exactly fit the crop is cleared rather than written as the centred value — a null crop and a crop that happens to be centred should not be two states. ── The preview is not object-cover ── It draws the rectangle: the picture scaled to `100/w` of the box and offset so the chosen corner lands at the origin. object-cover shows the largest window of the slot's shape that fits and nothing else — it can be panned and it cannot be zoomed, so a preview built on it would silently ignore half of what this control produces. ── Also here ── buildSite now hands the site an av-club URL and user. That is the first piece of publishing images cropped rather than cropping them in the browser with CSS: the plugin knows the sidecar registry, the site knows a URL. Inert until the site uses it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ import { stat, readdir, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { db } from 'officerdb/db';
|
||||
import { fofosAdminSettings } from '../db/schema';
|
||||
import { sidecarPort } from '@@/sidecar-registry';
|
||||
import { getOwnerUser } from 'officerdb';
|
||||
import { readDatabases } from './databases';
|
||||
|
||||
/**
|
||||
@@ -139,6 +141,12 @@ export async function buildSite(secrets: {
|
||||
if (!row?.rootPath) throw new Error('No root location is set.');
|
||||
|
||||
const websiteDir = join(row.rootPath, 'website');
|
||||
// Absent when av-club is not installed. The build is told, rather than left to fail on a fetch to a
|
||||
// port that is not there — and it can then say so plainly instead of timing out.
|
||||
const avClubPort = sidecarPort('av-club');
|
||||
// av-club resolves every path against a user's own media directory, so the build has to say who it
|
||||
// is working for. The owner, because that is whose root location this plugin administers.
|
||||
const owner = await getOwnerUser();
|
||||
const databases = await readDatabases();
|
||||
if (!databases.production.name || !databases.production.exists) {
|
||||
throw new Error('The production database does not exist yet.');
|
||||
@@ -160,6 +168,18 @@ export async function buildSite(secrets: {
|
||||
FOFOS_API_TOKEN: secrets.apiToken,
|
||||
ADMIN_SESSION_SECRET: secrets.sessionSecret,
|
||||
FOFOS_MEDIA_DIR: join(row.rootPath, 'media'),
|
||||
/*
|
||||
How the build reaches av-club.
|
||||
|
||||
The build crops each placement to the exact shape and size its slot renders at, rather than
|
||||
shipping a whole photograph and asking CSS to hide most of it. That needs an encoder, and the
|
||||
rule is that every encoder is av-club — so the plugin, which knows the sidecar registry, hands
|
||||
the site a URL and the site knows nothing else about the platform.
|
||||
|
||||
`x-officer-user` is av-club's whole authentication, and the build has to send it: the sidecar
|
||||
resolves paths against that user's own media directory.
|
||||
*/
|
||||
...(avClubPort && owner?.email ? { AV_CLUB_URL: `http://127.0.0.1:${avClubPort}`, AV_CLUB_USER: owner?.email ?? '' } : {}),
|
||||
// Only used to build absolute URLs in the output — og:image, canonical links. The real domain
|
||||
// belongs in the checkout's own env, where it is a deployment fact rather than one this invented.
|
||||
PUBLIC_URL: process.env.FOFOS_PUBLIC_URL ?? 'http://127.0.0.1',
|
||||
|
||||
Reference in New Issue
Block a user