-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(frontend): fix cannot redirect into chat/project page after create project from home page #151
Changes from 4 commits
70fdfa7
0ae45c0
49fc8af
e7cbacc
a735614
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,6 +7,9 @@ | |||||||||||||||||||||||||||||||||||||
ChevronRight, | ||||||||||||||||||||||||||||||||||||||
Maximize, | ||||||||||||||||||||||||||||||||||||||
ExternalLink, | ||||||||||||||||||||||||||||||||||||||
RefreshCcw, | ||||||||||||||||||||||||||||||||||||||
ZoomIn, | ||||||||||||||||||||||||||||||||||||||
ZoomOut, | ||||||||||||||||||||||||||||||||||||||
} from 'lucide-react'; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
export default function WebPreview() { | ||||||||||||||||||||||||||||||||||||||
|
@@ -15,6 +18,7 @@ | |||||||||||||||||||||||||||||||||||||
const [displayPath, setDisplayPath] = useState('/'); | ||||||||||||||||||||||||||||||||||||||
const [history, setHistory] = useState<string[]>(['/']); | ||||||||||||||||||||||||||||||||||||||
const [currentIndex, setCurrentIndex] = useState(0); | ||||||||||||||||||||||||||||||||||||||
const [scale, setScale] = useState(0.7); | ||||||||||||||||||||||||||||||||||||||
const iframeRef = useRef(null); | ||||||||||||||||||||||||||||||||||||||
const containerRef = useRef<{ projectPath: string; domain: string } | null>( | ||||||||||||||||||||||||||||||||||||||
null | ||||||||||||||||||||||||||||||||||||||
|
@@ -49,13 +53,34 @@ | |||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||
const json = await response.json(); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
await new Promise((resolve) => setTimeout(resolve, 200)); | ||||||||||||||||||||||||||||||||||||||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
containerRef.current = { | ||||||||||||||||||||||||||||||||||||||
projectPath, | ||||||||||||||||||||||||||||||||||||||
domain: json.domain, | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
setBaseUrl(`http://${json.domain}`); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const checkUrlStatus = async (url: string) => { | ||||||||||||||||||||||||||||||||||||||
let status = 0; | ||||||||||||||||||||||||||||||||||||||
while (status !== 200) { | ||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||
const res = await fetch(url, { method: 'HEAD' }); | ||||||||||||||||||||||||||||||||||||||
status = res.status; | ||||||||||||||||||||||||||||||||||||||
if (status !== 200) { | ||||||||||||||||||||||||||||||||||||||
console.log(`URL status: ${status}. Retrying...`); | ||||||||||||||||||||||||||||||||||||||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||
console.error('Error checking URL status:', err); | ||||||||||||||||||||||||||||||||||||||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const baseUrl = `http://${json.domain}`; | ||||||||||||||||||||||||||||||||||||||
await checkUrlStatus(baseUrl); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
setBaseUrl(baseUrl); | ||||||||||||||||||||||||||||||||||||||
setDisplayPath('/'); | ||||||||||||||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||||||||||||||
console.error('fetching url error:', error); | ||||||||||||||||||||||||||||||||||||||
|
@@ -109,6 +134,21 @@ | |||||||||||||||||||||||||||||||||||||
setDisplayPath(history[currentIndex + 1]); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
const reloadIframe = () => { | ||||||||||||||||||||||||||||||||||||||
const iframe = document.getElementById('myIframe') as HTMLIFrameElement; | ||||||||||||||||||||||||||||||||||||||
if (iframe) { | ||||||||||||||||||||||||||||||||||||||
iframe.src = iframe.src; | ||||||||||||||||||||||||||||||||||||||
setScale(0.7); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix self-assignment issue in reload function. The current implementation assigns const reloadIframe = () => {
const iframe = document.getElementById('myIframe') as HTMLIFrameElement;
if (iframe) {
- iframe.src = iframe.src;
+ const currentSrc = iframe.src;
+ iframe.src = '';
+ setTimeout(() => {
+ iframe.src = currentSrc;
+ }, 10);
setScale(0.7);
}
}; 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 140-140: src is assigned to itself. This is where is assigned. (lint/correctness/noSelfAssign) 🪛 GitHub Check: autofix[failure] 140-140: |
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const zoomIn = () => { | ||||||||||||||||||||||||||||||||||||||
setScale((prevScale) => Math.min(prevScale + 0.1, 2)); // 最大缩放比例为 2 | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const zoomOut = () => { | ||||||||||||||||||||||||||||||||||||||
setScale((prevScale) => Math.max(prevScale - 0.1, 0.5)); // 最小缩放比例为 0.5 | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||
<div className="flex flex-col w-full h-full"> | ||||||||||||||||||||||||||||||||||||||
|
@@ -119,7 +159,7 @@ | |||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
className="h-8 w-8" | ||||||||||||||||||||||||||||||||||||||
className="h-6 w-6" | ||||||||||||||||||||||||||||||||||||||
onClick={goBack} | ||||||||||||||||||||||||||||||||||||||
disabled={!baseUrl || currentIndex === 0} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
|
@@ -128,12 +168,20 @@ | |||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
className="h-8 w-8" | ||||||||||||||||||||||||||||||||||||||
className="h-6 w-6" | ||||||||||||||||||||||||||||||||||||||
onClick={goForward} | ||||||||||||||||||||||||||||||||||||||
disabled={!baseUrl || currentIndex >= history.length - 1} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<ChevronRight className="h-4 w-4" /> | ||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
className="h-6 w-6" | ||||||||||||||||||||||||||||||||||||||
onClick={reloadIframe} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<RefreshCcw /> | ||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
{/* URL Input */} | ||||||||||||||||||||||||||||||||||||||
|
@@ -150,6 +198,24 @@ | |||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
{/* Actions */} | ||||||||||||||||||||||||||||||||||||||
<div className="flex items-center gap-1"> | ||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
onClick={zoomOut} | ||||||||||||||||||||||||||||||||||||||
className="h-8 w-8" | ||||||||||||||||||||||||||||||||||||||
disabled={!baseUrl} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<ZoomOut className="h-4 w-4" /> | ||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
onClick={zoomIn} | ||||||||||||||||||||||||||||||||||||||
className="h-8 w-8" | ||||||||||||||||||||||||||||||||||||||
disabled={!baseUrl} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
<ZoomIn className="h-4 w-4" /> | ||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||
variant="ghost" | ||||||||||||||||||||||||||||||||||||||
size="icon" | ||||||||||||||||||||||||||||||||||||||
|
@@ -175,9 +241,17 @@ | |||||||||||||||||||||||||||||||||||||
<div className="relative flex-1 w-full h-full"> | ||||||||||||||||||||||||||||||||||||||
{baseUrl ? ( | ||||||||||||||||||||||||||||||||||||||
<iframe | ||||||||||||||||||||||||||||||||||||||
id="myIframe" | ||||||||||||||||||||||||||||||||||||||
ref={iframeRef} | ||||||||||||||||||||||||||||||||||||||
src={`${baseUrl}${displayPath}`} | ||||||||||||||||||||||||||||||||||||||
className="absolute inset-0 w-full h-full border-none bg-background" | ||||||||||||||||||||||||||||||||||||||
className="absolute inset-0 w-full h-80% border-none bg-background" | ||||||||||||||||||||||||||||||||||||||
style={{ | ||||||||||||||||||||||||||||||||||||||
transform: `scale(${scale})`, | ||||||||||||||||||||||||||||||||||||||
transformOrigin: 'top left', | ||||||||||||||||||||||||||||||||||||||
width: `calc(100% / ${scale})`, | ||||||||||||||||||||||||||||||||||||||
height: `calc(100% / ${scale})`, | ||||||||||||||||||||||||||||||||||||||
border: 'none', | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
) : ( | ||||||||||||||||||||||||||||||||||||||
<div className="absolute inset-0 w-full h-full flex items-center justify-center bg-background"> | ||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Removed ProjectProvider wrapper - verify context dependencies.
You've removed the
ProjectProvider
wrapper from aroundProjectModal
and its children. This simplifies the component hierarchy, but ensure thatProjectModal
and other child components don't depend on context data previously provided byProjectProvider
.🏁 Script executed:
Length of output: 363
Action Required: Address ProjectModal's Context Dependency
ProjectModal
component (atfrontend/src/components/chat/project-modal.tsx
) still usesuseContext(ProjectContext)
(line 24), and imports{ ProjectContext, ProjectProvider }
.ProjectProvider
wrapper inchat-layout.tsx
,ProjectModal
will no longer receive the expected context, which could lead to runtime errors or unexpected behavior.ProjectProvider
wrapper aroundProjectModal
and its children, or refactorProjectModal
to remove its reliance onProjectContext
(or provide default values/props as needed).ProjectContext
are updated consistently throughout the codebase.