Spaces:
Building
Building
handle redirect errors
Browse files
components/editor/preview/index.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { defaultHTML } from "@/lib/consts";
|
|
| 15 |
import { HistoryNotification } from "../history-notification";
|
| 16 |
import { api } from "@/lib/api";
|
| 17 |
import { toast } from "sonner";
|
|
|
|
| 18 |
|
| 19 |
export const Preview = ({ isNew }: { isNew: boolean }) => {
|
| 20 |
const {
|
|
@@ -31,6 +32,7 @@ export const Preview = ({ isNew }: { isNew: boolean }) => {
|
|
| 31 |
previewPage,
|
| 32 |
setPreviewPage,
|
| 33 |
setLastSavedPages,
|
|
|
|
| 34 |
} = useEditor();
|
| 35 |
const {
|
| 36 |
isEditableModeEnabled,
|
|
@@ -49,6 +51,7 @@ export const Preview = ({ isNew }: { isNew: boolean }) => {
|
|
| 49 |
const [stableHtml, setStableHtml] = useState<string>("");
|
| 50 |
const [throttledHtml, setThrottledHtml] = useState<string>("");
|
| 51 |
const lastUpdateTimeRef = useRef<number>(0);
|
|
|
|
| 52 |
|
| 53 |
useEffect(() => {
|
| 54 |
if (!previewPage && pages.length > 0) {
|
|
@@ -290,6 +293,10 @@ export const Preview = ({ isNew }: { isNew: boolean }) => {
|
|
| 290 |
};
|
| 291 |
}, [isEditableModeEnabled, stableHtml, throttledHtml, previewPage]);
|
| 292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
const promoteVersion = async () => {
|
| 294 |
setIsPromotingVersion(true);
|
| 295 |
await api
|
|
@@ -530,7 +537,26 @@ export const Preview = ({ isNew }: { isNew: boolean }) => {
|
|
| 530 |
</div>
|
| 531 |
) : (
|
| 532 |
<>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
<iframe
|
|
|
|
| 534 |
id="preview-iframe"
|
| 535 |
ref={iframeRef}
|
| 536 |
className={classNames(
|
|
@@ -546,31 +572,32 @@ export const Preview = ({ isNew }: { isNew: boolean }) => {
|
|
| 546 |
"/",
|
| 547 |
"-"
|
| 548 |
)}--rev-${currentCommit.slice(0, 7)}.static.hf.space`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 549 |
: undefined
|
| 550 |
}
|
| 551 |
srcDoc={
|
| 552 |
-
!currentCommit
|
| 553 |
? isNew
|
| 554 |
? throttledHtml || defaultHTML
|
| 555 |
: stableHtml
|
| 556 |
: undefined
|
| 557 |
}
|
| 558 |
-
onLoad={
|
| 559 |
-
!currentCommit
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
setupIframeListeners();
|
| 571 |
-
}
|
| 572 |
-
: undefined
|
| 573 |
-
}
|
| 574 |
sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-modals allow-forms"
|
| 575 |
allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; clipboard-read; clipboard-write; display-capture; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; serial; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"
|
| 576 |
/>
|
|
|
|
| 15 |
import { HistoryNotification } from "../history-notification";
|
| 16 |
import { api } from "@/lib/api";
|
| 17 |
import { toast } from "sonner";
|
| 18 |
+
import { RefreshCcw, TriangleAlert } from "lucide-react";
|
| 19 |
|
| 20 |
export const Preview = ({ isNew }: { isNew: boolean }) => {
|
| 21 |
const {
|
|
|
|
| 32 |
previewPage,
|
| 33 |
setPreviewPage,
|
| 34 |
setLastSavedPages,
|
| 35 |
+
hasUnsavedChanges,
|
| 36 |
} = useEditor();
|
| 37 |
const {
|
| 38 |
isEditableModeEnabled,
|
|
|
|
| 51 |
const [stableHtml, setStableHtml] = useState<string>("");
|
| 52 |
const [throttledHtml, setThrottledHtml] = useState<string>("");
|
| 53 |
const lastUpdateTimeRef = useRef<number>(0);
|
| 54 |
+
const [iframeKey, setIframeKey] = useState(0);
|
| 55 |
|
| 56 |
useEffect(() => {
|
| 57 |
if (!previewPage && pages.length > 0) {
|
|
|
|
| 293 |
};
|
| 294 |
}, [isEditableModeEnabled, stableHtml, throttledHtml, previewPage]);
|
| 295 |
|
| 296 |
+
const refreshIframe = () => {
|
| 297 |
+
setIframeKey((prev) => prev + 1);
|
| 298 |
+
};
|
| 299 |
+
|
| 300 |
const promoteVersion = async () => {
|
| 301 |
setIsPromotingVersion(true);
|
| 302 |
await api
|
|
|
|
| 537 |
</div>
|
| 538 |
) : (
|
| 539 |
<>
|
| 540 |
+
{!isNew && hasUnsavedChanges && !currentCommit && (
|
| 541 |
+
<div className="top-0 left-0 right-0 z-20 bg-amber-500/90 backdrop-blur-sm border-b border-amber-600 px-4 py-2 flex items-center justify-between gap-3 text-sm w-full">
|
| 542 |
+
<div className="flex items-center gap-2 flex-1">
|
| 543 |
+
<TriangleAlert className="size-4 text-amber-900 flex-shrink-0" />
|
| 544 |
+
<span className="text-amber-900 font-medium">
|
| 545 |
+
Preview with unsaved changes. If you experience redirection
|
| 546 |
+
errors, try refreshing the preview.
|
| 547 |
+
</span>
|
| 548 |
+
</div>
|
| 549 |
+
<button
|
| 550 |
+
onClick={refreshIframe}
|
| 551 |
+
className="px-3 py-1 bg-amber-900 hover:bg-amber-800 text-amber-50 rounded-md font-medium transition-colors whitespace-nowrap flex items-center gap-1.5"
|
| 552 |
+
>
|
| 553 |
+
<RefreshCcw className="size-4 text-amber-50 flex-shrink-0" />
|
| 554 |
+
Refresh
|
| 555 |
+
</button>
|
| 556 |
+
</div>
|
| 557 |
+
)}
|
| 558 |
<iframe
|
| 559 |
+
key={iframeKey}
|
| 560 |
id="preview-iframe"
|
| 561 |
ref={iframeRef}
|
| 562 |
className={classNames(
|
|
|
|
| 572 |
"/",
|
| 573 |
"-"
|
| 574 |
)}--rev-${currentCommit.slice(0, 7)}.static.hf.space`
|
| 575 |
+
: !isNew && !hasUnsavedChanges && project?.space_id
|
| 576 |
+
? `https://${project.space_id.replaceAll(
|
| 577 |
+
"/",
|
| 578 |
+
"-"
|
| 579 |
+
)}.static.hf.space`
|
| 580 |
: undefined
|
| 581 |
}
|
| 582 |
srcDoc={
|
| 583 |
+
!currentCommit && (isNew || hasUnsavedChanges)
|
| 584 |
? isNew
|
| 585 |
? throttledHtml || defaultHTML
|
| 586 |
: stableHtml
|
| 587 |
: undefined
|
| 588 |
}
|
| 589 |
+
onLoad={() => {
|
| 590 |
+
if (!currentCommit && (isNew || hasUnsavedChanges)) {
|
| 591 |
+
if (iframeRef?.current?.contentWindow?.document?.body) {
|
| 592 |
+
iframeRef.current.contentWindow.document.body.scrollIntoView({
|
| 593 |
+
block: isAiWorking ? "end" : "start",
|
| 594 |
+
inline: "nearest",
|
| 595 |
+
behavior: isAiWorking ? "instant" : "smooth",
|
| 596 |
+
});
|
| 597 |
+
}
|
| 598 |
+
setupIframeListeners();
|
| 599 |
+
}
|
| 600 |
+
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 601 |
sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-modals allow-forms"
|
| 602 |
allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; clipboard-read; clipboard-write; display-capture; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; serial; sync-xhr; usb; vr ; wake-lock; xr-spatial-tracking"
|
| 603 |
/>
|