@mevdragon/vidfarm-devcli 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/GETTING_STARTED.developers.md +1 -26
- package/README.md +3 -0
- package/SKILL.developer.md +419 -8
- package/auto-create-templates/AUTO_CREATE_TEMPLATES.md +475 -0
- package/auto-create-templates/extractor-system-prompt.md +113 -0
- package/auto-create-templates/production-graph.schema.json +276 -0
- package/auto-create-templates/runbook.md +140 -0
- package/auto-create-templates/template-plan.schema.json +230 -0
- package/auto-create-templates/template-planner-prompt.md +75 -0
- package/dist/src/account-pages-legacy.js +9064 -0
- package/dist/src/account-pages.js +41 -620
- package/dist/src/app.js +6627 -244
- package/dist/src/cli.js +386 -26
- package/dist/src/config.js +12 -2
- package/dist/src/context.js +35 -35
- package/dist/src/db.js +1016 -53
- package/dist/src/dev-app-legacy.js +693 -0
- package/dist/src/dev-app.js +4 -904
- package/dist/src/domain.js +1 -1
- package/dist/src/editor-chat-history.js +72 -0
- package/dist/src/editor-chat.js +202 -0
- package/dist/src/frontend/flockposter-cache-store.js +116 -0
- package/dist/src/frontend/homepage-client.js +114 -0
- package/dist/src/frontend/homepage-shared.js +3 -0
- package/dist/src/frontend/homepage-store.js +27 -0
- package/dist/src/frontend/homepage-view.js +147 -0
- package/dist/src/frontend/page-runtime-client.js +100 -0
- package/dist/src/frontend/page-runtime-store.js +8 -0
- package/dist/src/frontend/template-editor-chat.js +2261 -0
- package/dist/src/homepage.js +695 -371
- package/dist/src/lib/template-style-options.js +95 -15
- package/dist/src/page-runtime.js +1 -0
- package/dist/src/page-shell.js +941 -0
- package/dist/src/primitive-context.js +163 -0
- package/dist/src/primitive-registry.js +340 -0
- package/dist/src/primitive-sdk.js +3 -0
- package/dist/src/primitives/remotion/html-image.js +28 -0
- package/dist/src/react-page-shell.js +34 -0
- package/dist/src/ready-post-schedule-component.js +1514 -0
- package/dist/src/registry.js +36 -17
- package/dist/src/runtime.js +6 -1
- package/dist/src/services/api-call-history.js +245 -0
- package/dist/src/services/auth.js +25 -3
- package/dist/src/services/billing.js +248 -9
- package/dist/src/services/chat-threads.js +88 -0
- package/dist/src/services/job-logs.js +14 -7
- package/dist/src/services/jobs.js +13 -2
- package/dist/src/services/providers.js +552 -133
- package/dist/src/services/rate-limits.js +236 -0
- package/dist/src/services/remotion.js +143 -16
- package/dist/src/services/storage.js +10 -8
- package/dist/src/services/template-certification.js +11 -2
- package/dist/src/services/template-loader.js +3 -1
- package/dist/src/services/template-sources.js +68 -3
- package/dist/src/template-editor-pages.js +2309 -0
- package/dist/src/template-editor-shell.js +1507 -0
- package/dist/src/worker.js +120 -22
- package/package.json +27 -4
- package/public/assets/homepage-app.js +54 -0
- package/public/assets/homepage-client-app.js +54 -0
- package/public/assets/page-runtime-client-app.js +68 -0
- package/dist/templates/vidfarm_template_0000/src/lib/images.js +0 -202
- package/dist/templates/vidfarm_template_0000/src/remotion/Root.js +0 -34
- package/dist/templates/vidfarm_template_0000/src/remotion/index.js +0 -3
- package/dist/templates/vidfarm_template_0000/src/sdk.js +0 -3
- package/dist/templates/vidfarm_template_0000/src/style-options.js +0 -51
- package/dist/templates/vidfarm_template_0000/src/template-dna.js +0 -9
- package/dist/templates/vidfarm_template_0000/src/template.js +0 -1447
- package/templates/vidfarm_template_0000/README.md +0 -100
- package/templates/vidfarm_template_0000/SKILL.md +0 -225
- package/templates/vidfarm_template_0000/assets/Abel-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/DMSerifDisplay-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/Montserrat[wght].ttf +0 -0
- package/templates/vidfarm_template_0000/assets/SourceCodePro[wght].ttf +0 -0
- package/templates/vidfarm_template_0000/assets/TikTokSans-SemiBold.ttf +0 -0
- package/templates/vidfarm_template_0000/assets/Yesteryear-Regular.ttf +0 -0
- package/templates/vidfarm_template_0000/composition.json +0 -11
- package/templates/vidfarm_template_0000/package.json +0 -27
- package/templates/vidfarm_template_0000/research/preview/.gitkeep +0 -1
- package/templates/vidfarm_template_0000/research/source_notes.md +0 -7
- package/templates/vidfarm_template_0000/src/lib/images.js +0 -202
- package/templates/vidfarm_template_0000/src/lib/images.ts +0 -241
- package/templates/vidfarm_template_0000/src/remotion/Root.js +0 -33
- package/templates/vidfarm_template_0000/src/remotion/Root.tsx +0 -75
- package/templates/vidfarm_template_0000/src/remotion/index.js +0 -3
- package/templates/vidfarm_template_0000/src/remotion/index.tsx +0 -4
- package/templates/vidfarm_template_0000/src/sdk.js +0 -3
- package/templates/vidfarm_template_0000/src/sdk.ts +0 -140
- package/templates/vidfarm_template_0000/src/style-options.js +0 -51
- package/templates/vidfarm_template_0000/src/style-options.ts +0 -60
- package/templates/vidfarm_template_0000/src/template-dna.js +0 -9
- package/templates/vidfarm_template_0000/src/template-dna.ts +0 -15
- package/templates/vidfarm_template_0000/src/template.js +0 -1447
- package/templates/vidfarm_template_0000/src/template.ts +0 -2049
- package/templates/vidfarm_template_0000/template.config.json +0 -21
- package/templates/vidfarm_template_0000/tmp/solobacterium-moorei-slideshow.request.json +0 -31
- package/templates/vidfarm_template_0000/tsconfig.json +0 -19
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { resolveAccountDisplayName, withAccountQuery } from "../page-shell.js";
|
|
4
|
+
import { isVideoPreview } from "./homepage-shared.js";
|
|
5
|
+
function DiscoverIcon() {
|
|
6
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M10 3v4" }), _jsx("path", { d: "M10 13v4" }), _jsx("path", { d: "M3 10h4" }), _jsx("path", { d: "M13 10h4" }), _jsx("path", { d: "m5.8 5.8 2.3 2.3" }), _jsx("path", { d: "m11.9 11.9 2.3 2.3" }), _jsx("path", { d: "m14.2 5.8-2.3 2.3" }), _jsx("path", { d: "m8.1 11.9-2.3 2.3" })] });
|
|
7
|
+
}
|
|
8
|
+
function LibraryIcon() {
|
|
9
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M4.5 4.5h3v11h-3z" }), _jsx("path", { d: "M8.7 4.5h3v11h-3z" }), _jsx("path", { d: "m13.4 5.1 2.3-.6 2.2 10.7-2.3.6z" })] });
|
|
10
|
+
}
|
|
11
|
+
function CalendarIcon() {
|
|
12
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "10", cy: "10", r: "7.2" }), _jsx("path", { d: "M10 6.3v4.1l2.8 1.7" })] });
|
|
13
|
+
}
|
|
14
|
+
function SettingsIcon() {
|
|
15
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M14.8 15.2a5.4 5.4 0 1 0-9.6 0" }), _jsx("circle", { cx: "10", cy: "6.8", r: "3.1" })] });
|
|
16
|
+
}
|
|
17
|
+
function SearchIcon() {
|
|
18
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "8.5", cy: "8.5", r: "5.8" }), _jsx("path", { d: "m13 13 4.2 4.2" })] });
|
|
19
|
+
}
|
|
20
|
+
function BookmarkIcon() {
|
|
21
|
+
return _jsx("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "M6 3.8h8a1 1 0 0 1 1 1v11.4l-5-2.9-5 2.9V4.8a1 1 0 0 1 1-1Z" }) });
|
|
22
|
+
}
|
|
23
|
+
function PrimaryNav({ account }) {
|
|
24
|
+
const items = account.isLoggedIn
|
|
25
|
+
? [
|
|
26
|
+
{ id: "discover", href: withAccountQuery("/discover", account.userId), label: "Discover", icon: _jsx(DiscoverIcon, {}) },
|
|
27
|
+
{ id: "library", href: withAccountQuery("/library", account.userId), label: "Library", icon: _jsx(LibraryIcon, {}) },
|
|
28
|
+
{ id: "calendar", href: withAccountQuery("/calendar", account.userId), label: "Calendar", icon: _jsx(CalendarIcon, {}) },
|
|
29
|
+
{ id: "settings", href: withAccountQuery("/settings", account.userId), label: "Settings", icon: _jsx(SettingsIcon, {}) }
|
|
30
|
+
]
|
|
31
|
+
: [
|
|
32
|
+
{ id: "discover", href: "/discover", label: "Discover", icon: _jsx(DiscoverIcon, {}) },
|
|
33
|
+
{ id: "login", href: "/login", label: "Login", icon: _jsx(SettingsIcon, {}) }
|
|
34
|
+
];
|
|
35
|
+
return (_jsx("nav", { className: "primary-nav", "aria-label": "Primary", children: items.map((item) => (_jsxs("a", { className: `nav-link${item.id === "discover" ? " is-active" : ""}`, href: item.href, children: [_jsx("span", { className: "nav-icon", "aria-hidden": "true", children: item.icon }), _jsx("span", { children: item.label })] }, item.id))) }));
|
|
36
|
+
}
|
|
37
|
+
function BrandLockup({ account }) {
|
|
38
|
+
const email = account.email?.trim() || "";
|
|
39
|
+
const derivedName = resolveAccountDisplayName({ displayName: account.displayName, email: account.email });
|
|
40
|
+
const href = withAccountQuery("/discover", account.userId);
|
|
41
|
+
return (_jsxs("a", { className: "brand-lockup", href: href, children: [_jsx("img", { className: "brand-logo-image", src: "/assets/logo-vidfarm.png", alt: "VidFarm AI" }), _jsxs("div", { className: "brand-copy", children: [_jsxs("div", { className: "brand-title brand-title-static", children: ["VidFarm", _jsx("span", { className: "brand-title-mobile-hidden", children: " AI" })] }), email ? (_jsxs("div", { className: "brand-account-meta", children: [derivedName, " ", _jsxs("span", { children: ["(", email, ")"] })] })) : null] })] }));
|
|
42
|
+
}
|
|
43
|
+
function CloseIcon() {
|
|
44
|
+
return _jsxs("svg", { viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: [_jsx("path", { d: "m5 5 10 10" }), _jsx("path", { d: "m15 5-10 10" })] });
|
|
45
|
+
}
|
|
46
|
+
function LazyVideo({ src, controls = true }) {
|
|
47
|
+
const ref = useRef(null);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const video = ref.current;
|
|
50
|
+
if (!video || video.src) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const load = () => {
|
|
54
|
+
if (!video.dataset.src || video.getAttribute("src")) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
video.setAttribute("src", video.dataset.src);
|
|
58
|
+
video.load();
|
|
59
|
+
};
|
|
60
|
+
if (!("IntersectionObserver" in window)) {
|
|
61
|
+
load();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const observer = new IntersectionObserver((entries) => {
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
if (!entry.isIntersecting) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
load();
|
|
70
|
+
observer.unobserve(entry.target);
|
|
71
|
+
}
|
|
72
|
+
}, {
|
|
73
|
+
rootMargin: "240px 0px"
|
|
74
|
+
});
|
|
75
|
+
observer.observe(video);
|
|
76
|
+
return () => observer.disconnect();
|
|
77
|
+
}, []);
|
|
78
|
+
return _jsx("video", { ref: ref, className: "preview", "data-src": src, preload: "metadata", muted: true, playsInline: true, controls: controls });
|
|
79
|
+
}
|
|
80
|
+
function CopyInlineButton({ text, label }) {
|
|
81
|
+
const [status, setStatus] = useState("");
|
|
82
|
+
const handleClick = async () => {
|
|
83
|
+
try {
|
|
84
|
+
await navigator.clipboard.writeText(text);
|
|
85
|
+
setStatus("done");
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
setStatus("error");
|
|
89
|
+
}
|
|
90
|
+
window.setTimeout(() => setStatus(""), 1600);
|
|
91
|
+
};
|
|
92
|
+
return (_jsxs("button", { className: "pill-tag copy-inline", type: "button", "data-state": status, "aria-label": status === "done" ? `${label} copied` : label, onClick: () => void handleClick(), children: [_jsx("span", { className: "copy-inline-label", children: label }), _jsx("span", { className: "copy-inline-feedback", "aria-hidden": "true", children: status === "error" ? "Couldn’t copy" : "Copied" })] }));
|
|
93
|
+
}
|
|
94
|
+
function CreateButton({ templateId, accountUserId }) {
|
|
95
|
+
const href = withAccountQuery(`/templates/${encodeURIComponent(templateId)}/editor/docs`, accountUserId);
|
|
96
|
+
return _jsx("a", { className: "cta-button", href: href, children: "Create" });
|
|
97
|
+
}
|
|
98
|
+
function BookmarkButton(input) {
|
|
99
|
+
const label = `${input.isBookmarked ? "Remove bookmark for " : "Bookmark "}${input.title}`;
|
|
100
|
+
return (_jsx("button", { className: "bookmark-button", type: "button", "data-active": input.isBookmarked ? "true" : "false", "aria-label": label, "aria-pressed": input.isBookmarked, title: label, onClick: () => input.onToggleBookmark?.(input.templateId), children: _jsx(BookmarkIcon, {}) }));
|
|
101
|
+
}
|
|
102
|
+
function TemplateCard(input) {
|
|
103
|
+
const { template } = input;
|
|
104
|
+
const media = template.previewUrl
|
|
105
|
+
? isVideoPreview(template.previewUrl)
|
|
106
|
+
? _jsx(LazyVideo, { src: template.previewUrl, controls: false })
|
|
107
|
+
: _jsx("img", { className: "preview", src: template.previewUrl, alt: `${template.title} preview`, loading: "lazy", decoding: "async" })
|
|
108
|
+
: _jsx("div", { className: "preview preview-empty", children: "No preview" });
|
|
109
|
+
return (_jsxs("li", { className: "discover-card row", "data-template-id": template.templateId, children: [template.previewUrl ? (_jsxs("button", { className: "discover-card-media discover-card-media-button", type: "button", "aria-label": `Open ${template.title} preview`, onClick: () => input.onOpenPreview?.(template), children: [media, _jsx("span", { className: "discover-card-media-affordance", "aria-hidden": "true", children: "View" })] })) : (_jsx("div", { className: "discover-card-media", children: media })), _jsxs("div", { className: "discover-card-copy", children: [_jsxs("div", { className: "discover-card-head", children: [_jsxs("div", { className: "discover-card-title-wrap", children: [_jsx("h2", { children: template.title }), _jsx("p", { className: "discover-card-meta", children: template.previewUrl ? "1 preview asset with editable handoff." : "Reference format with editable handoff." })] }), _jsxs("div", { className: "discover-card-actions", children: [_jsx(BookmarkButton, { templateId: template.templateId, title: template.title, isBookmarked: input.isBookmarked, onToggleBookmark: input.onToggleBookmark }), _jsx(CreateButton, { templateId: template.templateId, accountUserId: input.accountUserId })] })] }), _jsx("div", { className: "discover-card-body", children: _jsx("p", { children: String(template.viralDna || "").trim() || "No summary provided for this format yet." }) }), _jsxs("div", { className: "discover-card-tags", children: [_jsx("div", { className: "pill-tag", children: isVideoPreview(template.previewUrl) ? "Video" : "Slideshow" }), _jsx(CopyInlineButton, { text: template.templateId, label: template.templateId }), _jsx(CopyInlineButton, { text: template.slugId, label: template.slugId })] })] })] }));
|
|
110
|
+
}
|
|
111
|
+
function PreviewModal(input) {
|
|
112
|
+
const { onClose, template } = input;
|
|
113
|
+
const previewUrl = template.previewUrl || "";
|
|
114
|
+
const isVideo = isVideoPreview(previewUrl);
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
const handleKeyDown = (event) => {
|
|
117
|
+
if (event.key === "Escape") {
|
|
118
|
+
onClose();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const previousOverflow = document.body.style.overflow;
|
|
122
|
+
document.body.style.overflow = "hidden";
|
|
123
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
124
|
+
return () => {
|
|
125
|
+
document.body.style.overflow = previousOverflow;
|
|
126
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
127
|
+
};
|
|
128
|
+
}, [onClose]);
|
|
129
|
+
return (_jsx("div", { className: "discover-media-modal-backdrop", role: "presentation", onClick: onClose, children: _jsxs("div", { className: "discover-media-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": "discover-media-modal-title", onClick: (event) => event.stopPropagation(), children: [_jsxs("div", { className: "discover-media-modal-head", children: [_jsx("h2", { id: "discover-media-modal-title", children: template.title }), _jsx("button", { className: "discover-media-modal-close", type: "button", "aria-label": "Close preview", onClick: onClose, children: _jsx(CloseIcon, {}) })] }), _jsx("div", { className: "discover-media-modal-stage", children: isVideo ? (_jsx("video", { src: previewUrl, controls: true, autoPlay: true, playsInline: true, preload: "metadata" })) : (_jsx("img", { src: previewUrl, alt: `${template.title} preview` })) })] }) }));
|
|
130
|
+
}
|
|
131
|
+
export function HomepageShell(input) {
|
|
132
|
+
const countLabel = input.error || `${input.visibleTemplates.length} visible`;
|
|
133
|
+
const showEmpty = !input.loading && !input.error && input.templates.length > 0 && input.visibleTemplates.length === 0;
|
|
134
|
+
const [previewTemplate, setPreviewTemplate] = useState(null);
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const phoneQuery = window.matchMedia("(max-width: 767px)");
|
|
137
|
+
const syncFilterPanelState = () => {
|
|
138
|
+
document.querySelectorAll(".discover-filter-panel").forEach((panel) => {
|
|
139
|
+
panel.open = !phoneQuery.matches;
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
syncFilterPanelState();
|
|
143
|
+
phoneQuery.addEventListener("change", syncFilterPanelState);
|
|
144
|
+
return () => phoneQuery.removeEventListener("change", syncFilterPanelState);
|
|
145
|
+
}, []);
|
|
146
|
+
return (_jsxs("section", { className: "frame discover-frame", children: [_jsxs("header", { className: "topbar", children: [_jsx(BrandLockup, { account: input.account }), _jsx("div", { className: "topbar-actions", children: _jsx(PrimaryNav, { account: input.account }) })] }), _jsx("div", { className: "frame-body", children: _jsxs("section", { className: "discover-shell", children: [_jsx("aside", { className: "discover-sidebar", children: _jsxs("details", { className: "discover-filter-panel", open: true, children: [_jsx("summary", { children: _jsx("span", { children: "Filters" }) }), _jsxs("div", { className: "discover-filter-panel-body", children: [_jsxs("div", { className: "discover-filter-block", children: [_jsx("div", { className: "label", children: "Filters" }), _jsx("p", { children: "Keep the controls pinned here and use the extra height to roam the catalog." })] }), _jsxs("div", { className: "discover-filter-group", children: [_jsx("label", { className: "label", htmlFor: "search", children: "Search formats" }), _jsxs("div", { className: "search-field", children: [_jsx("span", { className: "search-icon", "aria-hidden": "true", children: _jsx(SearchIcon, {}) }), _jsx("input", { id: "search", type: "search", placeholder: "Search templates, hooks, media styles", autoComplete: "off", value: input.searchQuery, onChange: (event) => input.onSearchQueryChange?.(event.target.value) })] })] }), _jsxs("div", { className: "discover-filter-group", children: [_jsx("label", { className: "label", htmlFor: "media-filter", children: "Media type" }), _jsx("select", { id: "media-filter", disabled: true, children: _jsx("option", { children: "All formats" }) })] }), _jsxs("div", { className: "discover-filter-group", children: [_jsx("label", { className: "label", children: "Shortlist" }), _jsxs("div", { className: "bookmarks-row", children: [_jsx("label", { className: "switch-label", htmlFor: "bookmarks-only", children: "Bookmarks only" }), _jsxs("label", { className: "switch-shell", htmlFor: "bookmarks-only", "data-active": input.bookmarksOnly ? "true" : "false", children: [_jsx("input", { id: "bookmarks-only", className: "switch-input", type: "checkbox", checked: input.bookmarksOnly, onChange: (event) => input.onBookmarksOnlyChange?.(event.target.checked) }), _jsx("span", { className: "switch-knob" })] })] })] })] })] }) }), _jsx("section", { className: "discover-results", children: _jsxs("div", { className: "discover-results-scroll", children: [_jsx("div", { className: "discover-count", id: "count", children: input.loading ? "Loading formats..." : countLabel }), _jsxs("div", { className: "discover-list-scroll", children: [_jsx("ul", { className: "discover-list", id: "template-list", children: input.loading ? (_jsx("li", { className: "empty-state discover-loading-card", children: "Loading formats..." })) : input.error ? (_jsx("li", { className: "empty-state discover-loading-card", children: "Unable to load formats." })) : input.templates.length === 0 ? (_jsx("li", { className: "empty-state discover-loading-card", children: "No formats available." })) : (input.visibleTemplates.map((template) => (_jsx(TemplateCard, { template: template, isBookmarked: input.bookmarks.has(template.templateId), onToggleBookmark: input.onToggleBookmark, onOpenPreview: setPreviewTemplate, accountUserId: input.account.userId }, template.templateId)))) }), _jsx("div", { className: "empty-state empty", id: "empty-state", "data-visible": showEmpty ? "true" : "false", children: "No formats match the current search and filter combination." })] })] }) })] }) }), previewTemplate ? _jsx(PreviewModal, { template: previewTemplate, onClose: () => setPreviewTemplate(null) }) : null] }));
|
|
147
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { createRoot } from "react-dom/client";
|
|
5
|
+
import { useStore } from "zustand";
|
|
6
|
+
import { createFlockPosterCacheStore, readFlockPosterCacheSnapshot } from "./flockposter-cache-store.js";
|
|
7
|
+
import { createPageRuntimeStore } from "./page-runtime-store.js";
|
|
8
|
+
import { TemplateEditorChat } from "./template-editor-chat.js";
|
|
9
|
+
function readBoot() {
|
|
10
|
+
const element = document.getElementById("page-runtime-boot");
|
|
11
|
+
if (!element?.textContent) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return JSON.parse(element.textContent);
|
|
15
|
+
}
|
|
16
|
+
function isoDaysFromNow(days) {
|
|
17
|
+
const date = new Date();
|
|
18
|
+
date.setDate(date.getDate() + days);
|
|
19
|
+
return date.toISOString();
|
|
20
|
+
}
|
|
21
|
+
async function hydrateFlockPosterCacheAtStartup(input) {
|
|
22
|
+
if (!input.userId) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const current = input.store.getState();
|
|
26
|
+
if (!input.force && current.channels.length && current.channelsUpdatedAt) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const params = new URLSearchParams({
|
|
30
|
+
start_date: isoDaysFromNow(-7),
|
|
31
|
+
end_date: isoDaysFromNow(30)
|
|
32
|
+
});
|
|
33
|
+
const response = await fetch(`/u/${encodeURIComponent(input.userId)}/calendar/feed?${params.toString()}`, {
|
|
34
|
+
headers: { accept: "application/json" }
|
|
35
|
+
});
|
|
36
|
+
const payload = await response.json().catch(() => null);
|
|
37
|
+
if (!response.ok || !payload) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
input.store.getState().setCalendarData({
|
|
41
|
+
channels: Array.isArray(payload.channels) ? payload.channels : [],
|
|
42
|
+
posts: Array.isArray(payload.posts) ? payload.posts : [],
|
|
43
|
+
rangeStart: payload.startDate || isoDaysFromNow(-7),
|
|
44
|
+
rangeEnd: payload.endDate || isoDaysFromNow(30),
|
|
45
|
+
replaceRange: true
|
|
46
|
+
});
|
|
47
|
+
window.dispatchEvent(new CustomEvent("vidfarm:flockposter-cache-updated"));
|
|
48
|
+
}
|
|
49
|
+
function PageRuntimeApp({ boot }) {
|
|
50
|
+
const store = useMemo(() => createPageRuntimeStore(boot), [boot]);
|
|
51
|
+
const title = useStore(store, (state) => state.boot.title);
|
|
52
|
+
const [chatRoot, setChatRoot] = useState(null);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
store.getState().setHydratedAt(new Date().toISOString());
|
|
55
|
+
document.documentElement.dataset.reactRuntime = "true";
|
|
56
|
+
document.documentElement.dataset.reactRuntimePage = boot.pageKind;
|
|
57
|
+
document.title = title;
|
|
58
|
+
}, [boot.pageKind, store, title]);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!boot.editorChat) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const nextRoot = document.querySelector("[data-template-editor-chat-root]");
|
|
64
|
+
setChatRoot(nextRoot instanceof HTMLElement ? nextRoot : null);
|
|
65
|
+
}, [boot.editorChat]);
|
|
66
|
+
return boot.editorChat && chatRoot
|
|
67
|
+
? createPortal(_jsx(TemplateEditorChat, { boot: boot.editorChat }), chatRoot)
|
|
68
|
+
: null;
|
|
69
|
+
}
|
|
70
|
+
const boot = readBoot();
|
|
71
|
+
const rootElement = document.getElementById("page-runtime-root");
|
|
72
|
+
const flockPosterCacheStore = createFlockPosterCacheStore(boot?.userId ?? null);
|
|
73
|
+
let flockPosterHydrationPromise = null;
|
|
74
|
+
function ensureFlockPosterCacheHydrated(options = {}) {
|
|
75
|
+
if (!options.force && flockPosterHydrationPromise) {
|
|
76
|
+
return flockPosterHydrationPromise;
|
|
77
|
+
}
|
|
78
|
+
flockPosterHydrationPromise = hydrateFlockPosterCacheAtStartup({
|
|
79
|
+
userId: boot?.userId ?? null,
|
|
80
|
+
store: flockPosterCacheStore,
|
|
81
|
+
force: options.force
|
|
82
|
+
}).catch(() => { });
|
|
83
|
+
return flockPosterHydrationPromise;
|
|
84
|
+
}
|
|
85
|
+
window.__vidfarmFlockPosterCache = {
|
|
86
|
+
readSnapshot: () => readFlockPosterCacheSnapshot(boot?.userId ?? null),
|
|
87
|
+
ensureHydrated: ensureFlockPosterCacheHydrated,
|
|
88
|
+
setChannelsData: (channels) => {
|
|
89
|
+
flockPosterCacheStore.getState().setChannelsData(channels);
|
|
90
|
+
window.dispatchEvent(new CustomEvent("vidfarm:flockposter-cache-updated"));
|
|
91
|
+
},
|
|
92
|
+
setCalendarData: (input) => {
|
|
93
|
+
flockPosterCacheStore.getState().setCalendarData(input);
|
|
94
|
+
window.dispatchEvent(new CustomEvent("vidfarm:flockposter-cache-updated"));
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
void ensureFlockPosterCacheHydrated();
|
|
98
|
+
if (boot && rootElement) {
|
|
99
|
+
createRoot(rootElement).render(_jsx(PageRuntimeApp, { boot: boot }));
|
|
100
|
+
}
|