feat(ui): add manual reload button to preview device toggles
This commit is contained in:
@@ -26,7 +26,7 @@ export default function PreviewTab() {
|
|||||||
|
|
||||||
const previews = anatomy?.hosting.previews ?? [];
|
const previews = anatomy?.hosting.previews ?? [];
|
||||||
// Find the port 3000 preview if it exists, otherwise fall back to null
|
// Find the port 3000 preview if it exists, otherwise fall back to null
|
||||||
const primaryPreview = previews.find(p => p.port === 3000);
|
const primaryPreview = previews.find((p) => p.port === 3000);
|
||||||
|
|
||||||
const [iframeSrc, setIframeSrc] = useState<string | null>(null);
|
const [iframeSrc, setIframeSrc] = useState<string | null>(null);
|
||||||
const iframeDomRef = useRef<HTMLIFrameElement | null>(null);
|
const iframeDomRef = useRef<HTMLIFrameElement | null>(null);
|
||||||
@@ -34,6 +34,7 @@ export default function PreviewTab() {
|
|||||||
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
||||||
|
|
||||||
const deviceMode = usePreviewToolbarStore((s) => s.deviceMode);
|
const deviceMode = usePreviewToolbarStore((s) => s.deviceMode);
|
||||||
|
const refreshKey = usePreviewToolbarStore((s) => s.refreshKey);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setIframeSrc(primaryPreview?.url ?? null);
|
setIframeSrc(primaryPreview?.url ?? null);
|
||||||
@@ -72,7 +73,7 @@ export default function PreviewTab() {
|
|||||||
</div>
|
</div>
|
||||||
) : iframeSrc ? (
|
) : iframeSrc ? (
|
||||||
<iframe
|
<iframe
|
||||||
key={iframeSrc}
|
key={`${iframeSrc}-${refreshKey}`}
|
||||||
src={iframeSrc}
|
src={iframeSrc}
|
||||||
title="Preview"
|
title="Preview"
|
||||||
ref={(el) => {
|
ref={(el) => {
|
||||||
@@ -91,7 +92,9 @@ export default function PreviewTab() {
|
|||||||
) : (
|
) : (
|
||||||
<div style={loaderWrap}>
|
<div style={loaderWrap}>
|
||||||
<p style={emptyText}>Preview not running on port 3000.</p>
|
<p style={emptyText}>Preview not running on port 3000.</p>
|
||||||
<p style={{...emptyText, fontSize: '0.75rem', marginTop: 8}}>Ask the AI to start the dev server.</p>
|
<p style={{ ...emptyText, fontSize: "0.75rem", marginTop: 8 }}>
|
||||||
|
Ask the AI to start the dev server.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from "zustand";
|
||||||
|
|
||||||
interface PreviewToolbarState {
|
interface PreviewToolbarState {
|
||||||
deviceMode: 'desktop' | 'mobile';
|
deviceMode: "desktop" | "mobile";
|
||||||
setDeviceMode: (mode: 'desktop' | 'mobile') => void;
|
setDeviceMode: (mode: "desktop" | "mobile") => void;
|
||||||
|
refreshKey: number;
|
||||||
|
triggerRefresh: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePreviewToolbarStore = create<PreviewToolbarState>((set) => ({
|
export const usePreviewToolbarStore = create<PreviewToolbarState>((set) => ({
|
||||||
deviceMode: 'desktop',
|
deviceMode: "desktop",
|
||||||
setDeviceMode: (mode) => set({ deviceMode: mode }),
|
setDeviceMode: (mode) => set({ deviceMode: mode }),
|
||||||
|
refreshKey: 0,
|
||||||
|
triggerRefresh: () => set((state) => ({ refreshKey: state.refreshKey + 1 })),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -91,12 +91,13 @@ export function ProjectIconRail({ workspace, projectId }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
import { Monitor, Smartphone } from "lucide-react";
|
import { Monitor, Smartphone, RotateCw } from "lucide-react";
|
||||||
import { usePreviewToolbarStore } from "./preview-toolbar/preview-toolbar-state";
|
import { usePreviewToolbarStore } from "./preview-toolbar/preview-toolbar-state";
|
||||||
|
|
||||||
function PreviewDeviceToggles() {
|
function PreviewDeviceToggles() {
|
||||||
const deviceMode = usePreviewToolbarStore((s) => s.deviceMode);
|
const deviceMode = usePreviewToolbarStore((s) => s.deviceMode);
|
||||||
const setDeviceMode = usePreviewToolbarStore((s) => s.setDeviceMode);
|
const setDeviceMode = usePreviewToolbarStore((s) => s.setDeviceMode);
|
||||||
|
const triggerRefresh = usePreviewToolbarStore((s) => s.triggerRefresh);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -109,6 +110,39 @@ function PreviewDeviceToggles() {
|
|||||||
border: "1px solid #e8e4dc",
|
border: "1px solid #e8e4dc",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<button
|
||||||
|
onClick={triggerRefresh}
|
||||||
|
title="Reload Preview"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: 28,
|
||||||
|
height: 26,
|
||||||
|
borderRadius: 6,
|
||||||
|
border: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "all 0.15s",
|
||||||
|
background: "transparent",
|
||||||
|
color: "#8c8580",
|
||||||
|
marginRight: 4,
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => (e.currentTarget.style.color = "#1a1a1a")}
|
||||||
|
onMouseLeave={(e) => (e.currentTarget.style.color = "#8c8580")}
|
||||||
|
>
|
||||||
|
<RotateCw size={14} />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 1,
|
||||||
|
height: 16,
|
||||||
|
background: "#d9d2c5",
|
||||||
|
alignSelf: "center",
|
||||||
|
marginRight: 4,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setDeviceMode("desktop")}
|
onClick={() => setDeviceMode("desktop")}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
Reference in New Issue
Block a user