|
|
@@ -7,17 +7,29 @@ const path = require('path');
|
|
|
|
|
|
// Use provided port or pick a random high port (49152-65535)
|
|
|
const PORT = process.env.BRAINSTORM_PORT || (49152 + Math.floor(Math.random() * 16383));
|
|
|
-const SCREEN_FILE = process.env.BRAINSTORM_SCREEN || '/tmp/brainstorm/screen.html';
|
|
|
-const SCREEN_DIR = path.dirname(SCREEN_FILE);
|
|
|
+const SCREEN_DIR = process.env.BRAINSTORM_DIR || '/tmp/brainstorm';
|
|
|
|
|
|
// Ensure screen directory exists
|
|
|
if (!fs.existsSync(SCREEN_DIR)) {
|
|
|
fs.mkdirSync(SCREEN_DIR, { recursive: true });
|
|
|
}
|
|
|
|
|
|
-// Create default screen if none exists
|
|
|
-if (!fs.existsSync(SCREEN_FILE)) {
|
|
|
- fs.writeFileSync(SCREEN_FILE, `<!DOCTYPE html>
|
|
|
+// Find the newest .html file in the directory by mtime
|
|
|
+function getNewestScreen() {
|
|
|
+ const files = fs.readdirSync(SCREEN_DIR)
|
|
|
+ .filter(f => f.endsWith('.html'))
|
|
|
+ .map(f => ({
|
|
|
+ name: f,
|
|
|
+ path: path.join(SCREEN_DIR, f),
|
|
|
+ mtime: fs.statSync(path.join(SCREEN_DIR, f)).mtime.getTime()
|
|
|
+ }))
|
|
|
+ .sort((a, b) => b.mtime - a.mtime);
|
|
|
+
|
|
|
+ return files.length > 0 ? files[0].path : null;
|
|
|
+}
|
|
|
+
|
|
|
+// Default waiting page (served when no screens exist yet)
|
|
|
+const WAITING_PAGE = `<!DOCTYPE html>
|
|
|
<html>
|
|
|
<head>
|
|
|
<title>Brainstorm Companion</title>
|
|
|
@@ -31,8 +43,7 @@ if (!fs.existsSync(SCREEN_FILE)) {
|
|
|
<h1>Brainstorm Companion</h1>
|
|
|
<p>Waiting for Claude to push a screen...</p>
|
|
|
</body>
|
|
|
-</html>`);
|
|
|
-}
|
|
|
+</html>`;
|
|
|
|
|
|
const app = express();
|
|
|
const server = http.createServer(app);
|
|
|
@@ -52,9 +63,10 @@ wss.on('connection', (ws) => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
-// Serve current screen with helper.js injected
|
|
|
+// Serve newest screen with helper.js injected
|
|
|
app.get('/', (req, res) => {
|
|
|
- let html = fs.readFileSync(SCREEN_FILE, 'utf-8');
|
|
|
+ const screenFile = getNewestScreen();
|
|
|
+ let html = screenFile ? fs.readFileSync(screenFile, 'utf-8') : WAITING_PAGE;
|
|
|
|
|
|
// Inject helper script before </body>
|
|
|
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
|
|
|
@@ -69,23 +81,35 @@ app.get('/', (req, res) => {
|
|
|
res.type('html').send(html);
|
|
|
});
|
|
|
|
|
|
-// Watch for screen file changes
|
|
|
-chokidar.watch(SCREEN_FILE).on('change', () => {
|
|
|
- console.log(JSON.stringify({ type: 'screen-updated', file: SCREEN_FILE }));
|
|
|
- // Notify all browsers to reload
|
|
|
- clients.forEach(ws => {
|
|
|
- if (ws.readyState === WebSocket.OPEN) {
|
|
|
- ws.send(JSON.stringify({ type: 'reload' }));
|
|
|
+// Watch for new or changed .html files in the directory
|
|
|
+chokidar.watch(SCREEN_DIR, { ignoreInitial: true })
|
|
|
+ .on('add', (filePath) => {
|
|
|
+ if (filePath.endsWith('.html')) {
|
|
|
+ console.log(JSON.stringify({ type: 'screen-added', file: filePath }));
|
|
|
+ // Notify all browsers to reload
|
|
|
+ clients.forEach(ws => {
|
|
|
+ if (ws.readyState === WebSocket.OPEN) {
|
|
|
+ ws.send(JSON.stringify({ type: 'reload' }));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .on('change', (filePath) => {
|
|
|
+ if (filePath.endsWith('.html')) {
|
|
|
+ console.log(JSON.stringify({ type: 'screen-updated', file: filePath }));
|
|
|
+ clients.forEach(ws => {
|
|
|
+ if (ws.readyState === WebSocket.OPEN) {
|
|
|
+ ws.send(JSON.stringify({ type: 'reload' }));
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
});
|
|
|
-});
|
|
|
|
|
|
server.listen(PORT, '127.0.0.1', () => {
|
|
|
console.log(JSON.stringify({
|
|
|
type: 'server-started',
|
|
|
port: PORT,
|
|
|
url: `http://localhost:${PORT}`,
|
|
|
- screen_dir: SCREEN_DIR,
|
|
|
- screen_file: SCREEN_FILE
|
|
|
+ screen_dir: SCREEN_DIR
|
|
|
}));
|
|
|
});
|