Skip to content

Commit 1d954a9

Browse files
committed
Fix Next.js server startup and improve playback debugging
- Switch from HTTPS to HTTP for development to avoid certificate issues - Add better player initialization detection with retry logic - Add comprehensive playback debugging logs - Improve frame synchronization between player and timeline - Add error and loading fallbacks to Player component
1 parent 2f0d240 commit 1d954a9

2 files changed

Lines changed: 97 additions & 65 deletions

File tree

MyApp.Client/components/editor/canvas/preview-canvas.tsx

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,51 +21,88 @@ export function PreviewCanvas({ project }: PreviewCanvasProps) {
2121
const timeline = getTimeline();
2222
const [isPlayerReady, setIsPlayerReady] = useState(false);
2323

24-
// Wait for player to be ready
24+
// Wait for player to be ready with better detection
2525
useEffect(() => {
26-
const timer = setTimeout(() => {
26+
let attempts = 0;
27+
const maxAttempts = 20;
28+
let timeoutId: NodeJS.Timeout;
29+
30+
const checkPlayerReady = () => {
2731
if (playerRef.current) {
28-
setIsPlayerReady(true);
32+
try {
33+
// Try to get current frame as a test of readiness
34+
playerRef.current.getCurrentFrame();
35+
console.log('Player is ready!');
36+
setIsPlayerReady(true);
37+
return;
38+
} catch (error) {
39+
console.log('Player not ready yet, attempt:', attempts + 1);
40+
}
41+
}
42+
43+
attempts++;
44+
if (attempts < maxAttempts) {
45+
timeoutId = setTimeout(checkPlayerReady, 100);
46+
} else {
47+
console.error('Player failed to initialize after', maxAttempts, 'attempts');
2948
}
30-
}, 100);
31-
return () => clearTimeout(timer);
49+
};
50+
51+
timeoutId = setTimeout(checkPlayerReady, 100);
52+
return () => clearTimeout(timeoutId);
3253
}, []);
3354

55+
// Sync current frame to player when timeline changes
56+
useEffect(() => {
57+
if (!playerRef.current || !isPlayerReady) {
58+
return;
59+
}
60+
61+
try {
62+
const currentPlayerFrame = playerRef.current.getCurrentFrame();
63+
if (timeline && currentPlayerFrame !== timeline.currentFrame) {
64+
playerRef.current.seekTo(timeline.currentFrame);
65+
}
66+
} catch (error) {
67+
console.error('Error seeking player:', error);
68+
}
69+
}, [timeline?.currentFrame, isPlayerReady]);
70+
3471
// Sync player playback state
3572
useEffect(() => {
3673
if (!playerRef.current || !isPlayerReady) {
37-
console.log('Player not ready yet');
74+
console.log('Player not ready for playback control');
3875
return;
3976
}
4077

4178
try {
79+
const player = playerRef.current;
80+
console.log('Current player state:', {
81+
isPlaying,
82+
currentFrame: player.getCurrentFrame(),
83+
isPlayerPlaying: player.isPlaying(),
84+
});
85+
4286
if (isPlaying) {
43-
console.log('Starting playback');
44-
playerRef.current.play();
87+
console.log('Calling play() on player');
88+
player.play();
89+
90+
// Verify playback started
91+
setTimeout(() => {
92+
console.log('Playback verification:', {
93+
isPlayerPlaying: player.isPlaying(),
94+
currentFrame: player.getCurrentFrame(),
95+
});
96+
}, 100);
4597
} else {
46-
console.log('Pausing playback');
47-
playerRef.current.pause();
98+
console.log('Calling pause() on player');
99+
player.pause();
48100
}
49101
} catch (error) {
50102
console.error('Error controlling playback:', error);
51103
}
52104
}, [isPlaying, isPlayerReady]);
53105

54-
// Handle frame updates from player
55-
const handleFrameUpdate = useCallback(
56-
(frame: number) => {
57-
if (timeline && frame !== timeline.currentFrame) {
58-
setCurrentFrame(frame);
59-
}
60-
},
61-
[timeline, setCurrentFrame]
62-
);
63-
64-
// Handle playback end
65-
const handleEnded = useCallback(() => {
66-
pause();
67-
}, [pause]);
68-
69106
if (!timeline) return null;
70107

71108
return (
@@ -101,6 +138,16 @@ export function PreviewCanvas({ project }: PreviewCanvasProps) {
101138
spaceKeyToPlayOrPause={false}
102139
autoPlay={false}
103140
loop={false}
141+
renderLoading={() => (
142+
<div className="flex items-center justify-center h-full bg-black">
143+
<div className="text-white">Loading...</div>
144+
</div>
145+
)}
146+
errorFallback={(error) => (
147+
<div className="flex items-center justify-center h-full bg-red-900/20">
148+
<div className="text-red-400">Error: {error.message}</div>
149+
</div>
150+
)}
104151
/>
105152
</div>
106153
</div>

MyApp.Client/server.js

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import { createServer } from 'https'
1+
import { createServer as createHttpServer } from 'http'
2+
import { createServer as createHttpsServer } from 'https'
23
import { parse } from 'url'
34
import next from 'next'
45
import { createProxyMiddleware } from 'http-proxy-middleware'
56
import fs from 'fs'
67
import path from 'path'
7-
import child_process from 'child_process'
88

99
const dev = process.env.NODE_ENV !== 'production'
1010
const hostname = 'localhost'
1111
const port = 3000
1212

13+
// Use HTTP for development unless certificates are explicitly provided
14+
const useHttps = !dev && process.env.USE_HTTPS === 'true'
15+
1316
const baseFolder =
1417
process.env.APPDATA !== undefined && process.env.APPDATA !== ''
1518
? `${process.env.APPDATA}/ASP.NET/https`
@@ -19,36 +22,6 @@ const certificateName = "myapp.client";
1922
const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
2023
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);
2124

22-
// Generate dev certificates if they don't exist (for dev mode only)
23-
if (dev) {
24-
console.log(`Certificate path: ${certFilePath}`);
25-
26-
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) {
27-
// mkdir to fix dotnet dev-certs error 3 https://github.com/dotnet/aspnetcore/issues/58330
28-
if (!fs.existsSync(baseFolder)) {
29-
fs.mkdirSync(baseFolder, { recursive: true });
30-
}
31-
if (
32-
0 !==
33-
child_process.spawnSync(
34-
"dotnet",
35-
[
36-
"dev-certs",
37-
"https",
38-
"--export-path",
39-
certFilePath,
40-
"--format",
41-
"Pem",
42-
"--no-password",
43-
],
44-
{ stdio: "inherit" }
45-
).status
46-
) {
47-
throw new Error("Could not create certificate.");
48-
}
49-
}
50-
}
51-
5225
const target = process.env.ASPNETCORE_HTTPS_PORT
5326
? `https://localhost:${process.env.ASPNETCORE_HTTPS_PORT}`
5427
: process.env.ASPNETCORE_URLS
@@ -77,12 +50,7 @@ const apiProxy = createProxyMiddleware({
7750
})
7851

7952
app.prepare().then(() => {
80-
const serverOptions = dev ? {
81-
key: fs.readFileSync(keyFilePath),
82-
cert: fs.readFileSync(certFilePath),
83-
} : {};
84-
85-
createServer(serverOptions, async (req, res) => {
53+
const requestHandler = async (req, res) => {
8654
try {
8755
const parsedUrl = parse(req.url, true)
8856
const { pathname } = parsedUrl
@@ -99,13 +67,30 @@ app.prepare().then(() => {
9967
res.statusCode = 500
10068
res.end('internal server error')
10169
}
102-
})
70+
}
71+
72+
// Create HTTP or HTTPS server based on environment
73+
let server
74+
if (useHttps && fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) {
75+
const serverOptions = {
76+
key: fs.readFileSync(keyFilePath),
77+
cert: fs.readFileSync(certFilePath),
78+
}
79+
server = createHttpsServer(serverOptions, requestHandler)
80+
console.log('Starting HTTPS server...')
81+
} else {
82+
server = createHttpServer(requestHandler)
83+
console.log('Starting HTTP server...')
84+
}
85+
86+
server
10387
.once('error', (err) => {
10488
console.error(err)
10589
process.exit(1)
10690
})
10791
.listen(port, () => {
108-
console.log(`> Ready on https://${hostname}:${port}`)
92+
const protocol = useHttps && fs.existsSync(certFilePath) ? 'https' : 'http'
93+
console.log(`> Ready on ${protocol}://${hostname}:${port}`)
10994
console.log(`> Proxying /api requests to ${target}`)
11095
})
11196
})

0 commit comments

Comments
 (0)