Commit Graph
14526 Commits
Author SHA1 Message Date
Tanish MankuandClaude Opus 4.7 55e470d2ca pagescene: drop view-only mutation gates + rename selector
Visitors can now fully interact with someone else's scene — move objects,
add shapes, edit colors, etc. The previous strict view-only mode is gone.
Save remains the only auth/ownership-gated action; its rewiring lands in
a follow-up.

Renames computeIsViewOnly to computeIsVisitingOthersScene to reflect the
remaining role (it only drives the PreviewBox today; Save-copy label and
Reset button consume it next). Drops getIsViewOnly()/useIsViewOnly()
early-returns from engine actions, drag-drop, gizmo attach, keybinds,
and the Outliner row controls. Strips !isViewOnly wrappers from chrome
in Stage3DBody so the prompt box, controls, panel, and model selector
show for everyone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 15:09:05 -07:00
Tanish Manku 5465aac4bc pagescene: silence webapp first-paint console errors
Two unrelated noise sources after wiring the editor into the webapp:

1. FontLoader was fetching /resources/fonts/CarterOneRegular.json,
   which exists in the Tauri public/ but not in the webapp's. Vite's
   SPA fallback returns index.html (200, HTML body), the FontLoader's
   progress callback fires "Font Loaded: 1" three times as it streams,
   then JSON.parse chokes on the leading `<` — surfaces as an
   unhandled promise rejection from LoadingPlaceHolderManager.
   Copy the same font asset into the webapp's public/ tree (same
   pattern Tauri and editor3d already use).

2. Editor.initialize() reads sceneContainerEl.offsetWidth/offsetHeight
   to size the WebGLRenderer + post-processing pipeline. On the
   webapp the flex chain (SidebarInset → wrapper → SceneContainer)
   isn't always laid out by first call, so the dimensions are
   transiently 0×0. setSize(0,0) then configureMain(0,0) allocates
   six post-process framebuffer attachments at 0 size, each emitting
   INVALID_FRAMEBUFFER_OPERATION until the next window.resize event
   cascades through and resizes them properly. Clamp the initial
   container offset to ≥1 (Math.max(1, ...)) and replace the
   `?? 0` fallbacks on the canvas dimensions with `|| 1`. First
   frame renders into a harmless 1×1, next resize fixes everything.
2026-05-13 14:37:30 -07:00
Tanish Manku 0e2594cbe9 webapp pagescene: persist editor state across SPA navigation
The 3D editor lib already exposes cacheJsonString + onSceneSerialized
props (Tauri wires them through useTabStore so per-tab scene state
survives tab switches). The webapp wasn't using them, so navigating
to /gallery, /create-image, etc. and back blew away whatever the user
had been building in the playground.

Add a small zustand store (mirrors enter-to-generate-store.ts) backed
by sessionStorage so the serialized JSON survives both SPA navigation
and tab reloads. Read cacheJsonString once via getState() on mount so
re-renders don't restart the engine; write back via the lib's
onSceneSerialized callback on unmount.

Scoped to the no-token playground: when sceneToken is in the URL the
server-loaded scene is the source of truth, so we neither restore
from cache (would override a shared scene) nor write the session back
into it (would later resurrect a stranger's scene as the playground).
2026-05-13 14:01:40 -07:00
Tanish Manku 67d1e73208 promptbox: route webapp Generate through OmniGenApi (fix 404)
PromptBox3D's handleWebEnqueue was POSTing to /v1/image_studio/prompt
via PromptsApi.enqueueImageGeneration, but that endpoint does not exist
on the Rust backend — image_studio_routes.rs only registers
/scene_snapshot and /update_job_status under /v1/image_studio (the
remaining routes live under legacy_routes/). The webapp's /create-image
and other generation flows already use OmniGenApi.generateImage hitting
/v1/omni_gen/image/generate; this commit aligns the 3D editor with that
modern path.

- Snapshot upload still goes through PromptsApi.uploadSceneSnapshot
  (that endpoint is the one image_studio route still in use).
- The returned snapshot media token is prepended to image_media_tokens
  ahead of the user's reference images, matching how the Tauri path
  treats the scene snapshot as the primary input.
- aspect_ratio uses commonAspectRatio for models that support the new
  shape, falling back to getCurrentAspectRatio() otherwise.
- On success: toast "Image added to queue" plus the same
  __storeTaskEnqueueMeta telemetry the Tauri path fires.
- Failure path routes through the existing handleError modal.
- Drops a dead 2-second setTimeout that delayed the success toast.

Tauri path unchanged — IsDesktopApp() still gates handleTauriEnqueue,
which goes through Tauri IPC and bypasses storyteller-web entirely.
2026-05-13 13:53:03 -07:00
Tanish Manku 37723f8602 pagescene: fix color picker not opening in Safari
The Color section in ControlPanelSceneObject had two issues that
compounded into a "no picker shows up" symptom in Safari:

1. setColor(editorEngine?.selected?.userData.color) wrote `undefined`
   into React state for shapes that never had a color set, which made
   <input value={undefined}> uncontrolled and gave the Button no inline
   background color (it fell back to the primary variant, so the swatch
   looked like a generic button instead of a white swatch).
2. The hidden <input type="color"> was a sibling of the swatch
   <label htmlFor={id}>, with h-0 w-0 opacity-0. Safari refuses to open
   the native color picker when the label's target input has no layout
   box — Chrome/Firefox tolerate it, Safari doesn't.

Fixes:
- Default the color state to "#ffffff" when userData.color is unset
  (both at setColor time and at value={} time for belt-and-braces).
- Seed userData.color = "#ffffff" at shape creation in addShape so
  the default carries through save/load roundtrips too.
- Move the <input type="color"> to be a CHILD of the Button label
  and position it absolute inset-0 over the swatch. Click lands
  directly on the input (no label[htmlFor] indirection Safari is
  flaky about) and the input now has a real full-size layout box.
2026-05-13 10:29:00 -07:00
Tanish Manku f977500553 Merge branch 'feature/webapp-pagescene' of github.com:storytold/storyteller-rust into feature/webapp-pagescene
# Conflicts:
#	frontend/apps/artcraft-webapp/src/pages/pagescene/pagescene.tsx
#	frontend/libs/components/pagescene/src/lib/Stage3DBody.tsx
#	frontend/libs/components/promptbox/src/lib/PromptBox3D.tsx
2026-05-13 09:36:17 -07:00
Tanish Manku 008fcfeaa7 pagescene: finish anonymous-use polish
- Gate File → Load my scene for anon: route through promptSignup
  instead of opening a dialog that would just error-toast on the
  silent listUserMediaFiles failure.
- Remove dead SettingsModal mount in Controls3D (no UI ever triggered
  it). Drops the @storyteller/ui-settings-modal import from this file.
- New AnonHintChip pill in the top-right corner of the playground
  ("Sign up to save"). Renders only when currentUserToken is undefined
  AND not in view-only mode; click routes to promptSignup. Tauri users
  never see it.
- Scaffolding for view-only PreviewBox: new component renders a small
  card with the author's generation result; returns null when no URL
  is supplied. Mounted in Stage3DBody under the isViewOnly guard,
  reading sceneMeta.previewImageUrl (new optional field). Data-path
  wiring (populating previewImageUrl from adapter.loadScene's
  response) is the next step — leaving the UI plumbing in place so
  that follow-up is purely data, not layout surgery.
2026-05-13 09:08:43 -07:00
bflatastic 52787c7fc0 add initial model selection on edit 3d 2026-05-13 21:57:09 +07:00
bflatastic 4deeb5e299 webapp: fix control panel sometimes renders overflowing right side 2026-05-13 20:41:10 +07:00
bflatastic cf95e4ce27 webapp: render model selector inside promptbox 2026-05-13 20:34:08 +07:00
bflatastic 572de13881 mobile gate edit 3d page, hold shift to boost movement speed 2026-05-13 20:22:43 +07:00
bflatastic e49c70b852 styling updates 2026-05-13 20:14:04 +07:00
bflatastic 076552fda4 webapp: fix flickering on threejs scene when sidebar collapsing/expanding, added edit 3d to homepage 2026-05-13 13:07:19 +07:00
Tanish Manku a9fa8d710a pagescene AssetMenu: fix featured Sets/Creatures never loading
useFeaturedObjects' auto-fetch effect synchronously flipped
firstFetch.current to IN_PROGRESS before calling fetchFeaturedObjects.
On AssetModal's first mount the EngineContext editor is null, so the
fetch bailed at `if (!editor) return`. When the editor later became
available the effect re-fired (editor is in fetchFeaturedObjects'
useCallback deps), but the IN_PROGRESS guard blocked it — the network
request never fired for any featured category. CHARACTER/OBJECT tabs
appeared populated only because they're merged with local demo arrays
inside AssetModal's assetTabs useMemo; Sets and Creatures have no demo
fallback so the bug was visible there.

Move the editor check into the auto-fetch effect itself and add editor
to its deps, so IN_PROGRESS isn't burned on the no-op call. Regression
from PR #1492.
2026-05-12 18:27:59 -07:00
Tanish Manku e120d009ae pagescene: add view-only mode + anon signup CTA
- view-only mode (driven by ownerToken !== currentUserToken): gates
  engine mutators (add/delete/toggle/transform/color), gizmo attach,
  delete/undo/redo keybinds, drag-to-add; hides editor chrome
  (OnboardingHelper, Controls3D, ControlsTopButtons, PromptBox3D,
  ControlPanelSceneObject, Outliner row toggles, model/cost buttons).
- new optional adapter.promptSignup; webapp adapter wires to existing
  useSignupCta modal. Save / Save-as-copy / Generate / Upload buttons
  call it when currentUserToken is undefined, so anon visitors hit a
  signup modal instead of silent failures.
- PromptBox3D gains onBeforeSubmit?: () => boolean hook; Stage3DBody
  uses it to route anon Generate clicks through promptSignup, since
  the Generate flow bypasses adapter.enqueueGeneration today.
2026-05-12 17:41:18 -07:00
Tanish MankuandClaude Opus 4.7 fcb0ddec56 webapp pagescene: fix top blank space; de-topbar shared lib layout
- styles.css: move .glass into @layer components so Tailwind's
  .absolute utility wins the cascade. OnboardingHelper was rendering
  position: relative and pushing the editor down on first paint until
  clicking dismissed it.
- SceneContainer + Stage3DBody: drop hardcoded calc(100vh - 68px) and
  height - 56 topbar offsets; the lib now fills its parent container.
- Webapp adapter: drop the +56 getViewportSize compensation now that
  the lib doesn't subtract a topbar from the supplied height.
- Tauri PageScene: wrap Stage3D in a calc(100vh - 56px) container
  (matching .topbar-spacer) so its shape is preserved.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 14:20:27 -07:00
bflatastic 3bb188eaf7 sidebar autocollapse edit 3d, positioning, page scrolling fix 2026-05-13 01:02:28 +07:00
Tanish Manku 2178afd736 webapp: mount pagescene at /pagescene with sidebar-aware viewport
Adds /pagescene (and /pagescene/:sceneToken) under the webapp's public
chrome (inside ProtectedLayout, outside RequireAuth) so anonymous users
can view scenes too. Adapter implementation mirrors the website's, with
two webapp-specific tweaks: imports the local useSession / showToast /
invalidateSession helpers, and getViewportSize returns the wrapper's
live ResizeObserver-measured rect so DnD hit-testing matches the visible
canvas (not window.innerWidth).

Sidebar handling: the lib's position-fixed UI is scoped to a wrapper
div with transform: translateZ(0), which creates a new containing block.
The wrapper renders inside SidebarInset's flex flow, so the editor sits
naturally to the right of the sidebar and below the topbar; expanded-
sidebar behavior is deferred (currently shrinks the page further per the
flex layout).

Sidebar nav gets an "Edit 3D" entry between Image and Video. Tailwind
config gets brand-primary/secondary/tertiary, action color, red/green/
blue DEFAULTs; styles.css adds .bg-ui-panel-gradient, .prevent-select,
.dot-typing — same gap-fills landed on the website.

No new endpoints. tsconfig churn from nx sync.
2026-05-12 09:18:13 -07:00
Tanish Manku 61c1aa720d artcraft host: import upload modals from @storyteller/ui-upload-modal
useTauriPageSceneAdapter, GlobalFileDropHandler, and UploadImagesButton
now pull UploadModal3D/Image/Splat from the shared lib. Removes the
host-local UploadModal3D/UploadModalImage/UploadModalSplat directories
since they're no longer referenced anywhere.

UploadModalMedia/ stays — it backs the host-only image-plane upload
adapter helpers, not the modal slots.
2026-05-12 09:11:11 -07:00
Tanish Manku 2d6af20d0b ui-upload-modal: lift UploadModal3D/Image/Splat into shared lib
Hoists the three feature-specific upload modals out of the artcraft
Tauri host into @storyteller/ui-upload-modal so the website (and any
future host) can render the same flows through PageScene's adapter
slots. Replaces direct `~/Classes/ApiManager` calls with @storyteller/api's
MediaUploadApi/MediaFilesApi.

Removes the old lib-internal UploadModal/UploadFiles/uploadAssets
placeholders (unused) and inlines the host-local enums
(MediaFileAnimationType, UploaderState/States, file-type enums) into
Types.ts. Adds UploadSpzFile to @storyteller/api's MediaUploadApi and
the SPLAT variant to FilterEngineCategories.
2026-05-12 09:11:11 -07:00
BFlat 0c2dd82161 unprotect webapp pages and signup cta on generate (#1504)
- public viewable pages
- signup cta on generate if not logged in
2026-05-12 22:57:10 +07:00
bflatastic 9ddf603ac8 webapp netlify redirects update 2026-05-12 21:57:39 +07:00
bflatastic 58b6b9c93f webapp netlify build fix 2026-05-12 21:52:25 +07:00
bflatastic 0246676dff fixed webapp netlify build script 2026-05-12 21:47:34 +07:00
BFlat 11a2547beb separate web marketing and web app (#1503)
cloned to webapp project and ripped out marketing stuff
2026-05-12 21:45:36 +07:00
Brandon Thomas d2dbef249c tauri providers - fal api key support (#1502) 2026-05-12 00:02:41 -04:00
Brandon Thomas 0efafe8043 FAL polling APIs + additional API bindings (#1501) 2026-05-11 21:12:10 -04:00
Brandon Thomas 25b2be92c8 artcraft router: image pipeline v2 w/ some fal models for testing (#1500) 2026-05-11 12:24:42 -04:00
BFlat 89f6015e3f Fix aspect ratio picker losing label after model switch (#1499)
When the stored `commonAspectRatio` (e.g. `SquareHd`) isn't in the
newly-selected model's `aspectRatios`, `PopoverMenu` toggle mode found
no selected item and collapsed the trigger to icon-only.

Reset to `model.defaultAspectRatio` from inside `AspectRatioPicker` so
the fix applies to all three callers (image/edit/3D). Drops the
duplicate workaround from `PromptBox3D`.
2026-05-11 20:24:01 +07:00
BFlat 3b889b6fdb website: make video button (#1498)
- added make video button to the create image page gallery card action
button row and the lightbox modal
- clicking it will redirect to the create video page and insert the
image as a reference automatically
2026-05-11 18:59:11 +07:00
Brandon Thomas 3ab2974d89 new fal client design to handle webhooks + queued requests with same API (#1497) 2026-05-10 07:48:13 -04:00
Brandon Thomas 220cf66dfc fal_client refactors ahead of a bigger one (#1496) 2026-05-09 19:46:32 -04:00
Tanish Manku 2d18a07843 3D PageScene: Componentize and big refactor (#1492) 2026-05-09 14:26:42 -07:00
Tanish Manku 369c552096 PageDraw: Generate fixes and performance boost (#1494) 2026-05-09 13:51:25 -07:00
Brandon Thomas 13a5dad3a5 beeble improvements, don't 500 on bad input (#1493) 2026-05-09 10:49:05 -04:00
bflatastic f8be6ea4c9 website: hide resolution picker, progress timer 5 mins 2026-05-09 16:35:18 +07:00
bflatastic 5f70776afe website: unified credits chip for mobile and desktop view 2026-05-09 09:28:23 +07:00
bflatastic 5c5a7d1182 credits in top navbar mobile 2026-05-09 09:12:20 +07:00
Brandon Thomas d0e5a05253 frontend api stuff (#1491) 2026-05-08 22:01:21 -04:00
Brandon Thomas 72e052fe7e add redirects for netlify 2026-05-08 21:44:01 -04:00
Brandon Thomas 7471259d28 fix frontend errors (missing vite config, type errors) (#1490) 2026-05-08 21:40:46 -04:00
Brandon Thomas ffde0b06c0 beeble webhook (#1489) 2026-05-08 20:06:09 -04:00
BFlat b4da753346 video background change feature (#1480)
- both app and website
2026-05-09 02:31:54 +07:00
Brandon Thomas 312c603cef remount 2026-05-08 13:45:18 -04:00
Brandon Thomas bdfa31421f beeble endpoint (#1488) 2026-05-08 13:44:41 -04:00
Brandon Thomas c78442cf71 beeble client (#1487) 2026-05-08 12:49:15 -04:00
Brandon ThomasandTanish Manku 58b64b694c Big tauri refactor: new consolidated commands, deprecate and remove duplication (#1486)
Co-authored-by: Tanish Manku <tanish2k09.dev@gmail.com>
2026-05-08 09:29:25 -04:00
BFlat f666e68dcd app: ask location before download (#1483)
- toggle in settings to enable disable ask location on download button
pressed
2026-05-08 16:25:27 +07:00
Brandon Thomas 5a7c253189 fal request logging (#1482) 2026-05-07 21:56:52 -04:00
Brandon Thomas 808beafd4c fal - no api key or webhook url in args (#1481) 2026-05-07 19:28:12 -04:00