reenable frontend

This commit is contained in:
Brandon Thomas committed 2026-04-08 10:29:39 -04:00
1 parent e2fe661bb7
commit 1622b68c64
9 files changed
+92 -73

No files matched your search

@@ -4,8 +4,8 @@ import Media from "../pages/media";
import PressKit from "../pages/press-kit";
import Navbar from "../components/navbar";
import { ToastContainer } from "../components/toast/toast";
// import CreateImage from "../pages/create-image";
// import CreateVideo from "../pages/create-video";
import CreateImage from "../pages/create-image";
import CreateVideo from "../pages/create-video";
import Landing2 from "../pages/landing2";
import LandingSD2 from "../pages/landing-sd2";
import TutorialsPage from "../pages/tutorials";
@@ -30,8 +30,8 @@ export function App() {
<Routes>
<Route path="/" element={<Landing2 />} />
{/* <Route path="/create-image" element={<CreateImage />} />
<Route path="/create-video" element={<CreateVideo />} /> */}
<Route path="/create-image" element={<CreateImage />} />
<Route path="/create-video" element={<CreateVideo />} />
<Route path="/seedance-2" element={<LandingSD2 />} />
<Route path="/download" element={<Download />} />
<Route path="/media" element={<Media />} />
@@ -17,8 +17,8 @@ import { TaskQueue } from "./task-queue";
const NAV_ITEMS = [
{ name: "Home", href: "/" },
// { name: "Image", href: "/create-image" },
// { name: "Video", href: "/create-video" },
{ name: "Image", href: "/create-image" },
{ name: "Video", href: "/create-video" },
{ name: "Tutorials", href: "/tutorials" },
{ name: "News", href: "/news" },
{ name: "FAQ", href: "/faq" },
+10 -9
View File
@@ -11,15 +11,16 @@ const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement,
);
// In development, route API through the Vite dev server origin to avoid CORS
if (import.meta.env.DEV) {
try {
const origin = window.location.origin;
StorytellerApiHostStore.getInstance().setApiSchemeAndHost(origin);
} catch (e) {
console.warn("Failed to set dev API host override", e);
}
}
// In development, route API through the Vite dev server proxy to avoid CORS,
// unless VITE_API_HOST is explicitly set (eg. for an unsafe browser that ignores CORS).
//if (import.meta.env.DEV && !import.meta.env.VITE_API_HOST) {
// try {
// const origin = window.location.origin;
// StorytellerApiHostStore.getInstance().setApiSchemeAndHost(origin);
// } catch (e) {
// console.warn("Failed to set dev API host override", e);
// }
//}
// Cache the referrer immediately — it can change or disappear on navigation.
// Only set once so subsequent in-site navigations don't overwrite the original.
@@ -50,9 +50,7 @@ const ROUTE_TO_FILTER: Record<string, string> = {
meshes: "meshes",
};
const getFilterMediaClass = (
filter: string,
): FilterMediaClasses[] | undefined => {
const getFilterMediaClass = (filter: string): FilterMediaClasses[] | undefined => {
switch (filter) {
case "image":
return [FilterMediaClasses.IMAGE];
@@ -61,11 +59,7 @@ const getFilterMediaClass = (
case "meshes":
return [FilterMediaClasses.DIMENSIONAL];
default:
return [
FilterMediaClasses.IMAGE,
FilterMediaClasses.VIDEO,
FilterMediaClasses.DIMENSIONAL,
];
return [FilterMediaClasses.IMAGE, FilterMediaClasses.VIDEO, FilterMediaClasses.DIMENSIONAL];
}
};
@@ -97,9 +91,7 @@ const getLabel = (item: any) => {
export default function Library() {
const { filter: filterParam } = useParams<{ filter?: string }>();
const navigate = useNavigate();
const activeFilter = filterParam
? (ROUTE_TO_FILTER[filterParam] ?? "all")
: "all";
const activeFilter = filterParam ? (ROUTE_TO_FILTER[filterParam] ?? "all") : "all";
const [username, setUsername] = useState<string | null>(null);
const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null);
@@ -121,7 +113,11 @@ export default function Library() {
const checkSession = async () => {
const usersApi = new UsersApi();
const response = await usersApi.GetSession();
if (response.success && response.data?.loggedIn && response.data.user) {
if (
response.success &&
response.data?.loggedIn &&
response.data.user
) {
setUsername(response.data.user.username);
setIsLoggedIn(true);
} else {
@@ -139,8 +135,8 @@ export default function Library() {
const thumbnail = isDimensional
? null
: getMediaThumbnail(item.media_links, item.media_class, {
size: THUMBNAIL_SIZES.MEDIUM,
});
size: THUMBNAIL_SIZES.MEDIUM,
});
return {
id: item.token,
@@ -173,9 +169,7 @@ export default function Library() {
if (response.success && response.data) {
const newItems = response.data
.filter(
(item: any) => item.media_type !== FilterMediaType.SCENE_JSON,
)
.filter((item: any) => item.media_type !== FilterMediaType.SCENE_JSON)
.map(mapApiItem);
if (reset) {
@@ -256,17 +250,17 @@ export default function Library() {
const navigatePrev =
currentIndex > 0
? () => {
const prev = flatItems[currentIndex - 1];
setLightboxItem(prev);
}
const prev = flatItems[currentIndex - 1];
setLightboxItem(prev);
}
: undefined;
const navigateNext =
currentIndex >= 0 && currentIndex < flatItems.length - 1
? () => {
const next = flatItems[currentIndex + 1];
setLightboxItem(next);
}
const next = flatItems[currentIndex + 1];
setLightboxItem(next);
}
: undefined;
const handleItemDeleted = useCallback((id: string) => {
@@ -347,11 +341,10 @@ export default function Library() {
<button
key={filter.id}
onClick={() => navigate(filter.route)}
className={`flex items-center gap-2 px-4 py-1.5 rounded-md text-sm font-medium transition-colors ${
activeFilter === filter.id
className={`flex items-center gap-2 px-4 py-1.5 rounded-md text-sm font-medium transition-colors ${activeFilter === filter.id
? "bg-ui-controls text-white"
: "text-white/60 hover:text-white"
}`}
}`}
>
<FontAwesomeIcon icon={filter.icon} className="text-xs" />
{filter.label}
@@ -393,8 +386,10 @@ export default function Library() {
</div>
) : allItems.length === 0 && !loading ? (
<div className="flex flex-col items-center justify-center py-20">
<p className="text-white/40 text-sm mb-4">No items yet.</p>
{/* <div className="flex gap-3">
<p className="text-white/40 text-sm mb-4">
No items yet. Start generating!
</p>
<div className="flex gap-3">
<Link to="/create-image">
<Button variant="primary" className="text-sm px-4 py-2">
Create Image
@@ -408,7 +403,7 @@ export default function Library() {
Create Video
</Button>
</Link>
</div> */}
</div>
</div>
) : (
<div className="space-y-6">
+3 -1
View File
@@ -60,7 +60,9 @@ export class ApiManager {
}
protected getApiSchemeAndHost(): string {
return StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const host = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
console.log('getSchemaAndHost()', host);
return host;
}
public async fetch<B, T>(
@@ -1,5 +1,8 @@
// Artcraft / Storyteller API backend
const DEFAULT_API_HOST = "https://api.storyteller.ai";
// Set VITE_API_HOST=http://localhost:12345 for local dev, or leave unset for production.
//const DEFAULT_API_HOST = (import.meta as any).env?.VITE_API_HOST || "https://api.storyteller.ai";
const DEFAULT_API_HOST = "http://localhost:12345";
// NB(bt,2025-09-25): 'nx' is creating multiple copies of the library with name
// mangling, so the singleton pattern fails to resolve to a single instance.
@@ -137,7 +137,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
tabIndex={-1}
className={twMerge(
"w-full group relative overflow-visible rounded-md border-[3px] transition-all focus:outline-none",
item.mediaClass === "video" ? "aspect-video" : "aspect-square",
"aspect-square",
selected || bulkSelected
? "border-primary"
: disableTooltipAndBadge
@@ -171,7 +171,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
alt={item.label}
className={twMerge(
"h-full w-full bg-black/30",
item.mediaClass === "video" || imageFit === "contain" ? "object-contain" : "object-cover",
imageFit === "contain" ? "object-contain" : "object-cover",
)}
draggable={false}
onError={onImageError}
@@ -187,7 +187,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
);
return (
<div className={twMerge("group relative w-full", item.mediaClass === "video" ? "aspect-video" : "aspect-square")}>
<div className={twMerge("group relative w-full", "aspect-square")}>
{/* dropdown menu */}
{mode !== "select" && (
<div
@@ -2,6 +2,9 @@
"files": [],
"include": [],
"references": [
{
"path": "../slider-v2"
},
{
"path": "../button-icon-select"
},
@@ -14,9 +17,6 @@
{
"path": "../camera-settings-modal"
},
{
"path": "../toaster"
},
{
"path": "../../tauri-utils"
},
@@ -26,29 +26,38 @@
{
"path": "../../model-list"
},
{
"path": "../modal"
},
{
"path": "../popover"
},
{
"path": "../slider-v2"
},
{
"path": "../../common"
},
{
"path": "../../api"
"path": "../tooltip"
},
{
"path": "../action-reminder-modal"
},
{
"path": "../label"
},
{
"path": "../button"
},
{
"path": "../input"
},
{
"path": "../gallery-modal"
},
{
"path": "../tooltip"
"path": "../toaster"
},
{
"path": "../button"
"path": "../../api"
},
{
"path": "../modal"
},
{
"path": "./tsconfig.lib.json"
@@ -43,6 +43,9 @@
"src/**/*.tsx"
],
"references": [
{
"path": "../slider-v2/tsconfig.lib.json"
},
{
"path": "../button-icon-select/tsconfig.lib.json"
},
@@ -55,9 +58,6 @@
{
"path": "../camera-settings-modal/tsconfig.lib.json"
},
{
"path": "../toaster/tsconfig.lib.json"
},
{
"path": "../../tauri-utils/tsconfig.lib.json"
},
@@ -67,29 +67,38 @@
{
"path": "../../model-list/tsconfig.lib.json"
},
{
"path": "../modal/tsconfig.lib.json"
},
{
"path": "../popover/tsconfig.lib.json"
},
{
"path": "../slider-v2/tsconfig.lib.json"
},
{
"path": "../../common/tsconfig.lib.json"
},
{
"path": "../../api/tsconfig.lib.json"
"path": "../tooltip/tsconfig.lib.json"
},
{
"path": "../action-reminder-modal/tsconfig.lib.json"
},
{
"path": "../label/tsconfig.lib.json"
},
{
"path": "../button/tsconfig.lib.json"
},
{
"path": "../input/tsconfig.lib.json"
},
{
"path": "../gallery-modal/tsconfig.lib.json"
},
{
"path": "../tooltip/tsconfig.lib.json"
"path": "../toaster/tsconfig.lib.json"
},
{
"path": "../button/tsconfig.lib.json"
"path": "../../api/tsconfig.lib.json"
},
{
"path": "../modal/tsconfig.lib.json"
}
]
}