/ index.html
index.html
  1  <!DOCTYPE html>
  2  <html>
  3    <head>
  4      <meta charset="UTF-8" />
  5      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  6      <title>FleetCode Terminal</title>
  7      <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
  8      <link rel="stylesheet" href="dist/styles.css" />
  9      <!-- Socket.IO client for web mode -->
 10      <script src="/socket.io/socket.io.js"></script>
 11      <style>
 12        body {
 13          margin: 0;
 14          padding: 0;
 15          font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
 16        }
 17      </style>
 18    </head>
 19    <body class="h-screen overflow-hidden bg-gray-900">
 20      <!-- Mobile hamburger menu -->
 21      <button id="mobile-menu-btn" class="mobile-menu-btn" title="Toggle Menu">
 22        <span class="hamburger-line"></span>
 23        <span class="hamburger-line"></span>
 24        <span class="hamburger-line"></span>
 25      </button>
 26      
 27      <!-- Mobile overlay (when sidebar is open) -->
 28      <div id="mobile-overlay" class="mobile-overlay"></div>
 29      
 30      <div class="flex h-full">
 31        <!-- Sidebar -->
 32        <div class="sidebar" id="sidebar">
 33          <div class="sidebar-header">
 34            <h1 class="sidebar-title">FleetCode</h1>
 35            <button id="open-settings" class="settings-btn" title="Settings">⚙️</button>
 36          </div>
 37  
 38          <div class="sidebar-content">
 39            <div class="sidebar-section">
 40              <div class="sidebar-section-header">
 41                <div class="sidebar-section-title">SESSIONS</div>
 42                <button id="new-session" class="section-add-btn" title="New Session">+</button>
 43              </div>
 44              <div id="session-list"></div>
 45            </div>
 46  
 47            <div class="sidebar-section" id="mcp-section" style="display: none;">
 48              <div class="sidebar-section-header">
 49                <div class="sidebar-section-title">MCP SERVERS</div>
 50                <button id="add-mcp-server" class="section-add-btn" title="Add MCP Server">+</button>
 51              </div>
 52              <div id="mcp-server-list"></div>
 53            </div>
 54          </div>
 55        </div>
 56  
 57        <!-- Main content -->
 58        <div class="flex-1 flex flex-col bg-black">
 59          <!-- Tabs -->
 60          <div id="tabs" class="tabs-container"></div>
 61  
 62          <!-- Session container -->
 63          <div id="session-container" class="flex-1 relative"></div>
 64        </div>
 65      </div>
 66  
 67      <!-- Session Configuration Modal -->
 68      <div id="config-modal" class="modal-overlay hidden">
 69        <div class="modal">
 70          <h2 class="modal-title">New Session Configuration</h2>
 71  
 72          <div class="form-group">
 73            <label class="form-label">Project Directory</label>
 74            <div class="directory-input-group">
 75              <input type="text" id="project-dir" class="form-input" readonly placeholder="Select a directory..." />
 76              <button id="browse-dir" class="btn-icon">Browse</button>
 77            </div>
 78          </div>
 79  
 80          <div class="form-group">
 81            <label class="form-label">Parent Branch</label>
 82            <select id="parent-branch" class="form-select">
 83              <option value="">Loading branches...</option>
 84            </select>
 85          </div>
 86  
 87          <div class="form-group">
 88            <label class="form-label">Branch Name (optional)</label>
 89            <input type="text" id="branch-name" class="form-input" placeholder="e.g., feature/add-login" />
 90            <span class="text-xs text-gray-400 mt-1 block">Custom branch name (will also be used as session name)</span>
 91          </div>
 92  
 93          <div class="form-group">
 94            <label class="form-label">Coding Agent</label>
 95            <select id="coding-agent" class="form-select">
 96              <option value="claude">Claude</option>
 97              <option value="codex">Codex</option>
 98              <option value="amp">Amp</option>
 99            </select>
100          </div>
101  
102          <div class="form-group">
103            <label class="flex items-center space-x-2 cursor-pointer">
104              <input type="checkbox" id="skip-permissions" class="form-checkbox" checked />
105              <span class="text-sm text-gray-300">Skip permissions (use --dangerously-skip-permissions)</span>
106            </label>
107          </div>
108  
109          <div class="form-group">
110            <label class="form-label">Setup Commands (optional)</label>
111            <textarea id="setup-commands" class="form-input" rows="3" placeholder="Commands to run before starting coding agent (one per line)&#10;e.g., export API_KEY=...&#10;source .env"></textarea>
112            <span class="text-xs text-gray-400 mt-1 block">These commands will be executed in order before the coding agent starts</span>
113          </div>
114  
115          <div class="btn-group">
116            <button id="cancel-session" class="btn-secondary">Cancel</button>
117            <button id="create-session" class="btn-primary">Create Session</button>
118          </div>
119        </div>
120      </div>
121  
122      <!-- MCP Server Details Modal -->
123      <div id="mcp-details-modal" class="modal-overlay hidden">
124        <div class="modal">
125          <h2 class="modal-title" id="mcp-details-title">Server Details</h2>
126  
127          <div id="mcp-details-content" class="space-y-3 text-sm text-gray-300">
128            <!-- Details will be populated here -->
129          </div>
130  
131          <div class="btn-group">
132            <button id="close-mcp-details" class="btn-secondary">Close</button>
133            <button id="remove-mcp-details" class="btn-danger">Remove Server</button>
134          </div>
135        </div>
136      </div>
137  
138      <!-- MCP Server Modal -->
139      <div id="mcp-modal" class="modal-overlay hidden">
140        <div class="modal">
141          <h2 class="modal-title">Add MCP Server</h2>
142  
143          <div class="form-group">
144            <label class="form-label">Server Name</label>
145            <input type="text" id="mcp-name" class="form-input" placeholder="e.g., my-server" />
146          </div>
147  
148          <div class="form-group">
149            <label class="form-label">Server Type</label>
150            <select id="mcp-type" class="form-select">
151              <option value="local">Local</option>
152              <option value="remote">Remote</option>
153            </select>
154          </div>
155  
156          <!-- Local Server Fields -->
157          <div id="local-fields">
158            <div class="form-group">
159              <label class="form-label">Command</label>
160              <input type="text" id="mcp-command" class="form-input" placeholder="e.g., node, npx" />
161            </div>
162  
163            <div class="form-group">
164              <label class="form-label">Arguments (space-separated)</label>
165              <input type="text" id="mcp-args" class="form-input" placeholder="e.g., /path/to/server.js or -s @modelcontextprotocol/server-filesystem" />
166            </div>
167  
168            <div class="form-group">
169              <label class="form-label">Environment Variables (optional, JSON)</label>
170              <textarea id="mcp-env" class="form-input" rows="3" placeholder='{"API_KEY": "your_api_key"}'></textarea>
171            </div>
172          </div>
173  
174          <!-- Remote Server Fields -->
175          <div id="remote-fields" style="display: none;">
176            <div class="form-group">
177              <label class="form-label">Server URL</label>
178              <input type="text" id="mcp-url" class="form-input" placeholder="https://your-server-url.com/mcp" />
179            </div>
180  
181            <div class="form-group">
182              <label class="form-label">Headers (optional, JSON)</label>
183              <textarea id="mcp-headers" class="form-input" rows="3" placeholder='{"Authorization": "Bearer your-token"}'></textarea>
184            </div>
185          </div>
186  
187          <div class="form-group">
188            <label class="form-label">Always Allow Tools (optional, comma-separated)</label>
189            <input type="text" id="mcp-always-allow" class="form-input" placeholder="e.g., tool1, tool2, tool3" />
190          </div>
191  
192          <div class="btn-group">
193            <button id="cancel-mcp" class="btn-secondary">Cancel</button>
194            <button id="add-mcp" class="btn-primary">Add Server</button>
195          </div>
196        </div>
197      </div>
198  
199      <!-- Diff Viewer Modal -->
200      <div id="diff-viewer-modal" class="modal-overlay hidden">
201        <div class="diff-viewer-modal">
202          <div class="diff-viewer-header">
203            <h2 class="modal-title" id="diff-viewer-title">Git Diff Viewer</h2>
204            <div class="diff-viewer-actions">
205              <button id="merge-to-parent-btn" class="btn-merge" disabled title="Merge worktree branch into parent">
206                Merge to Parent
207              </button>
208              <button id="close-diff-viewer" class="diff-viewer-close" title="Close">×</button>
209            </div>
210          </div>
211          
212          <div class="diff-viewer-content">
213            <!-- File List Sidebar -->
214            <div class="diff-file-list" id="diff-file-list">
215              <button id="toggle-diff-sidebar" class="diff-sidebar-toggle">
216                <span class="toggle-expand">&gt;&gt;</span>
217                <span class="toggle-collapse">&lt;&lt;</span>
218              </button>
219              <div class="diff-loading">Loading diff...</div>
220            </div>
221            
222            <!-- Diff Display -->
223            <div class="diff-display" id="diff-display">
224              <div class="diff-empty">Select a file to view changes</div>
225            </div>
226          </div>
227        </div>
228      </div>
229  
230      <!-- Settings Modal -->
231      <div id="settings-modal" class="modal-overlay hidden">
232        <div class="modal">
233          <h2 class="modal-title">Terminal Settings</h2>
234  
235          <div class="form-group">
236            <label class="form-label">Theme</label>
237            <select id="settings-theme" class="form-select">
238              <option value="macos-light">macOS Terminal (Light)</option>
239              <option value="macos-dark">macOS Terminal (Dark)</option>
240              <option value="solarized-dark">Solarized Dark</option>
241              <option value="dracula">Dracula</option>
242              <option value="one-dark">One Dark</option>
243              <option value="github-dark">GitHub Dark</option>
244            </select>
245          </div>
246  
247          <div class="form-group">
248            <label class="form-label">Font Family</label>
249            <select id="settings-font-family" class="form-select">
250              <option value="Menlo, Monaco, 'Courier New', monospace">Menlo</option>
251              <option value="'SF Mono', Monaco, 'Courier New', monospace">SF Mono</option>
252              <option value="Monaco, 'Courier New', monospace">Monaco</option>
253              <option value="'Courier New', Courier, monospace">Courier New</option>
254              <option value="'Source Code Pro', monospace">Source Code Pro</option>
255              <option value="'Fira Code', monospace">Fira Code</option>
256              <option value="'JetBrains Mono', monospace">JetBrains Mono</option>
257              <option value="Consolas, monospace">Consolas</option>
258            </select>
259          </div>
260  
261          <div class="form-group">
262            <label class="form-label">Font Size</label>
263            <input type="number" id="settings-font-size" class="form-input" min="8" max="32" placeholder="11" />
264          </div>
265  
266          <div class="form-group">
267            <label class="flex items-center space-x-2 cursor-pointer">
268              <input type="checkbox" id="settings-cursor-blink" class="form-checkbox" />
269              <span class="text-sm text-gray-300">Cursor Blink</span>
270            </label>
271          </div>
272  
273          <div class="form-group">
274            <label class="form-label">Worktree Root Directory</label>
275            <div class="directory-input-group">
276              <input type="text" id="settings-worktree-dir" class="form-input" readonly placeholder="~/worktrees" />
277              <button id="browse-worktree-dir" class="btn-icon">Browse</button>
278            </div>
279            <span class="text-xs text-gray-400 mt-1 block">Directory where session worktrees will be stored</span>
280          </div>
281  
282          <div class="btn-group">
283            <button id="cancel-settings" class="btn-secondary">Cancel</button>
284            <button id="reset-settings" class="btn-secondary">Reset to Default</button>
285            <button id="save-settings" class="btn-primary">Save</button>
286          </div>
287        </div>
288      </div>
289  
290      <script>
291        // Detect if running in Electron or Web browser
292        const isElectron = typeof window !== "undefined" && 
293                           typeof window.process !== "undefined" &&
294                           window.process.type === "renderer";
295        
296        if (isElectron) {
297          // Electron: use require (CommonJS from tsc)
298          require('./dist/renderer.js');
299        } else {
300          // Web browser: use bundled version (IIFE from esbuild)
301          const script = document.createElement('script');
302          script.src = './dist/renderer.web.js';
303          script.type = 'text/javascript';
304          document.body.appendChild(script);
305        }
306      </script>
307    </body>
308  </html>