Skip to content

Add story edit panel: cover image upload, genre, language, NSFW #177

@realproject7

Description

@realproject7

Context

PlotLink has two existing API endpoints that the OWS app can use:

  • `/api/upload-cover` — upload cover image (will require wallet signature after plotlink#1136)
  • `/api/storyline/update` — update genre, language, NSFW flag, cover CID (requires wallet signature)

The OWS app already signs messages via OWS wallet (`createOwsAccount` in `app/lib/publish.ts`). We can reuse this to call both endpoints.

Depends On

Changes

1. Add Edit Panel UI

After a story is published, show an "Edit" button/section in the preview panel or story detail area. The edit panel should allow:

  • Cover image: upload area (WebP/JPEG, max 500KB, 600×900px recommended), preview, remove
  • Genre: dropdown selector (same as publish flow)
  • Language: dropdown selector (same as publish flow)
  • NSFW: checkbox toggle

Only show for published stories where the OWS wallet is the author.

2. Cover Image Upload Flow

IMPORTANT: Use `createOwsAccount` + `account.signMessage()` for signing — NOT raw `owsSignMsg` directly. The `createOwsAccount` wrapper (line 34-51 in publish.ts) normalizes the signature format to be compatible with viem's `recoverMessageAddress` on the PlotLink server.

```ts
import { createOwsAccount } from "./publish";

const account = createOwsAccount(walletName, walletAddress);

// Sign for upload
const timestamp = Date.now();
const uploadMessage = `PlotLink: Upload cover image\nTimestamp: ${timestamp}`;
const uploadSignature = await account.signMessage({ message: uploadMessage });

// Build FormData
const formData = new FormData();
formData.append("file", imageFile);
formData.append("message", uploadMessage);
formData.append("signature", uploadSignature);

// Upload to PlotLink API
const res = await fetch(`${PLOTLINK_URL}/api/upload-cover`, { method: "POST", body: formData });
const { cid } = await res.json();
```

3. Update Story Metadata Flow

```ts
// Sign for update (different message format — must match PlotLink API regex exactly)
const timestamp = Date.now();
const updateMessage = `PlotLink: Update storyline #${storylineId}\nTimestamp: ${timestamp}`;
const updateSignature = await account.signMessage({ message: updateMessage });

// POST to PlotLink update API
await fetch(`${PLOTLINK_URL}/api/storyline/update`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
storylineId,
signature: updateSignature,
message: updateMessage,
coverCid, genre, language, isNsfw
}),
});
```

Note: Upload and update use DIFFERENT message formats:

  • Upload: `"PlotLink: Upload cover image\nTimestamp: {ts}"`
  • Update: `"PlotLink: Update storyline #{id}\nTimestamp: {ts}"`

The update message format must match the regex `/^PlotLink: Update storyline #(\d+)\nTimestamp: (\d+)$/` exactly.

4. Add Helpers in publish.ts

Create reusable helpers:

```ts
export async function uploadCoverImage(
walletName: string,
walletAddress: `0x${string}`,
imageFile: File
): Promise // returns CID

export async function updateStoryline(
walletName: string,
walletAddress: `0x${string}`,
storylineId: number,
updates: { coverCid?: string | null; genre?: string; language?: string; isNsfw?: boolean }
): Promise
```

Both use `createOwsAccount` internally for signing.

5. Post-Publish Guidance Update

After publishing, update the guidance message to mention the edit panel is now available directly in the OWS app (instead of directing to plotlink.xyz).

Files

  • `app/lib/publish.ts` — add `updateStoryline()` and `uploadCoverImage()` helpers
  • `app/web/components/PreviewPanel.tsx` — add edit panel UI for published stories
  • `app/web/components/StoriesPage.tsx` — wire up edit actions
  • `app/routes/publish.ts` — add update route handler if needed

Acceptance Criteria

  • Edit panel visible for published stories authored by the OWS wallet
  • Cover image upload works via signed API call
  • Genre, language, NSFW editable via signed update API call
  • Uses `createOwsAccount` wrapper for all signing (not raw `owsSignMsg`)
  • Message formats match what PlotLink API expects exactly
  • Error handling for failed uploads/updates with clear messages
  • Works on both desktop and mobile views

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agentenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions