feat: add terminal type selection in directory picker
Add CSS styling for the terminal type dropdown that was already implemented in the JavaScript but wasn't visible due to missing styles. The dropdown allows users to choose between: - Standard Shell (bash/zsh) - default - Claude Code CLI - runs claude --dangerously-skip-permissions When Claude Code CLI is selected: - Session picker is skipped (not needed) - Terminal automatically launches with claude --dangerously-skip-permissions - Mode is automatically set to 'session' Changes: - Add .terminal-type-selection, .terminal-type-select styles to terminal.css - Match existing modal styling (background, borders, focus states) - JavaScript was already implemented from previous work Resolves: "Claude Code CLI still not appears under terminal > new terminal" Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -284,12 +284,14 @@
|
||||
}
|
||||
|
||||
.recent-directories,
|
||||
.custom-directory {
|
||||
.custom-directory,
|
||||
.terminal-type-selection {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.recent-directories label,
|
||||
.custom-directory label {
|
||||
.custom-directory label,
|
||||
.terminal-type-selection label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
@@ -298,6 +300,28 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.terminal-type-select {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 6px;
|
||||
color: #e0e0e0;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-type-select:hover {
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.terminal-type-select:focus {
|
||||
outline: none;
|
||||
border-color: #4a9eff;
|
||||
box-shadow: 0 0 0 3px rgba(74, 158, 255, 0.1);
|
||||
}
|
||||
|
||||
.directory-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -166,19 +166,25 @@ class TerminalManager {
|
||||
sessionId = null,
|
||||
mode = 'mixed',
|
||||
silent = false,
|
||||
skipSessionPicker = false
|
||||
skipSessionPicker = false,
|
||||
terminalType = null
|
||||
} = options;
|
||||
|
||||
// Show directory picker if no working directory provided
|
||||
const selectedDir = workingDir || await this.showDirectoryPicker();
|
||||
const selection = workingDir
|
||||
? { directory: workingDir, terminalType: terminalType || 'standard' }
|
||||
: await this.showDirectoryPicker();
|
||||
|
||||
if (!selectedDir) {
|
||||
if (!selection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { directory: selectedDir, terminalType: selectedTerminalType } = selection;
|
||||
|
||||
// If no session provided and not skipping picker, show session picker
|
||||
let sessionSelection = null;
|
||||
if (!sessionId && !skipSessionPicker) {
|
||||
if (!sessionId && !skipSessionPicker && selectedTerminalType !== 'claude-cli') {
|
||||
// Skip session picker if Claude Code CLI terminal is selected
|
||||
sessionSelection = await this.showSessionPicker();
|
||||
// If user cancelled session picker, still create terminal but without session
|
||||
// sessionSelection will be null or { sessionId: string, source: 'web'|'local' } or { sessionId: 'new', source: 'new' }
|
||||
@@ -213,15 +219,25 @@ class TerminalManager {
|
||||
// Switch to new terminal
|
||||
this.switchToTerminal(terminalId);
|
||||
|
||||
// Handle terminal type specific initialization
|
||||
if (selectedTerminalType === 'claude-cli') {
|
||||
// Wait a moment for terminal to be ready
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
// Launch Claude CLI with skip permissions flag
|
||||
await this.launchCommand(terminalId, 'claude --dangerously-skip-permissions\n');
|
||||
await this.setMode(terminalId, 'session');
|
||||
|
||||
if (!silent) {
|
||||
showToast('Claude Code CLI terminal created', 'success');
|
||||
}
|
||||
} else if (sessionSelection && sessionSelection.sessionId) {
|
||||
// Auto-launch Claude CLI if session was selected
|
||||
if (sessionSelection && sessionSelection.sessionId) {
|
||||
if (sessionSelection.sessionId !== 'new') {
|
||||
await this.launchClaudeCLI(terminalId, sessionSelection.sessionId, sessionSelection.source);
|
||||
} else {
|
||||
// Launch Claude CLI without session for new session
|
||||
await this.launchClaudeCLI(terminalId, null, 'new');
|
||||
}
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
const sessionMsg = sessionSelection && sessionSelection.sessionId && sessionSelection.sessionId !== 'new'
|
||||
@@ -229,6 +245,11 @@ class TerminalManager {
|
||||
: sessionSelection && sessionSelection.sessionId === 'new' ? ' (New Session)' : '';
|
||||
showToast(`Terminal created${sessionMsg}`, 'success');
|
||||
}
|
||||
} else {
|
||||
if (!silent) {
|
||||
showToast('Terminal created', 'success');
|
||||
}
|
||||
}
|
||||
|
||||
return terminalId;
|
||||
} catch (error) {
|
||||
@@ -281,6 +302,17 @@ class TerminalManager {
|
||||
<label>Custom Path</label>
|
||||
<input type="text" class="directory-input" placeholder="Enter absolute path..." value="${escapeHtml(recentDirs[0])}">
|
||||
</div>
|
||||
<div class="terminal-type-selection">
|
||||
<label>Terminal Type</label>
|
||||
<select class="terminal-type-select">
|
||||
<option value="standard">Standard Shell (bash/zsh)</option>
|
||||
<option value="claude-cli">Claude Code CLI (with --dangerously-skip-permissions)</option>
|
||||
</select>
|
||||
<small style="display: block; margin-top: 0.5rem; color: var(--text-secondary);">
|
||||
Standard Shell: Regular terminal with bash/zsh<br>
|
||||
Claude Code CLI: Automatically starts with claude --dangerously-skip-permissions
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-secondary btn-cancel">Cancel</button>
|
||||
@@ -293,8 +325,10 @@ class TerminalManager {
|
||||
setTimeout(() => modal.classList.add('visible'), 10);
|
||||
|
||||
const input = modal.querySelector('.directory-input');
|
||||
const terminalTypeSelect = modal.querySelector('.terminal-type-select');
|
||||
const createBtn = modal.querySelector('.btn-create');
|
||||
let selectedDir = recentDirs[0];
|
||||
let selectedTerminalType = 'standard';
|
||||
|
||||
// Handle directory selection
|
||||
modal.querySelectorAll('.directory-item').forEach(item => {
|
||||
@@ -311,17 +345,22 @@ class TerminalManager {
|
||||
selectedDir = input.value;
|
||||
});
|
||||
|
||||
// Handle terminal type selection
|
||||
terminalTypeSelect.addEventListener('change', () => {
|
||||
selectedTerminalType = terminalTypeSelect.value;
|
||||
});
|
||||
|
||||
// Handle enter key
|
||||
input.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
resolve(selectedDir);
|
||||
resolve({ directory: selectedDir, terminalType: selectedTerminalType });
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle create
|
||||
createBtn.addEventListener('click', () => {
|
||||
resolve(selectedDir);
|
||||
resolve({ directory: selectedDir, terminalType: selectedTerminalType });
|
||||
cleanup();
|
||||
});
|
||||
|
||||
@@ -583,6 +622,25 @@ class TerminalManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a command in the terminal
|
||||
*/
|
||||
async launchCommand(terminalId, command) {
|
||||
const terminal = this.terminals.get(terminalId);
|
||||
if (!terminal || !terminal.ws || terminal.ws.readyState !== WebSocket.OPEN) {
|
||||
console.error('[TerminalManager] Terminal not ready for command launch');
|
||||
return;
|
||||
}
|
||||
|
||||
// Send command to terminal
|
||||
terminal.ws.send(JSON.stringify({
|
||||
type: 'input',
|
||||
data: command
|
||||
}));
|
||||
|
||||
console.log(`[TerminalManager] Launched command in terminal ${terminalId}: ${command.trim()}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract project name from session metadata
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user