feat: highlight session cards with orange border when 'esc to interrupt' is detected

- Add checkForEscPrompt() method to scan buffer content on each update
- Emit 'esc-prompt-change' event when prompt presence changes
- Apply orange border to session card when prompt is detected
- Case-insensitive search for 'esc to interrupt' text

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mario Zechner 2025-06-20 05:07:56 +02:00
parent 3ec549344b
commit de8952d34a
2 changed files with 41 additions and 3 deletions

View file

@ -27,6 +27,7 @@ export class SessionCard extends LitElement {
@property({ type: Object }) session!: Session;
@state() private killing = false;
@state() private killingFrame = 0;
@state() private hasEscPrompt = false;
private killingInterval: number | null = null;
@ -47,6 +48,10 @@ export class SessionCard extends LitElement {
);
}
private handleEscPromptChange(event: CustomEvent) {
this.hasEscPrompt = event.detail.hasEscPrompt;
}
private async handleKillClick(e: Event) {
e.stopPropagation();
e.preventDefault();
@ -151,10 +156,9 @@ export class SessionCard extends LitElement {
render() {
return html`
<div
class="bg-vs-bg border border-vs-border rounded shadow cursor-pointer overflow-hidden ${this
.killing
class="bg-vs-bg rounded shadow cursor-pointer overflow-hidden ${this.killing
? 'opacity-60'
: ''}"
: ''} ${this.hasEscPrompt ? 'border-2 border-orange-500' : 'border border-vs-border'}"
@click=${this.handleCardClick}
>
<!-- Compact Header -->
@ -211,6 +215,7 @@ export class SessionCard extends LitElement {
.sessionId=${this.session.id}
class="w-full h-full"
style="pointer-events: none;"
@esc-prompt-change=${this.handleEscPromptChange}
></vibe-terminal-buffer>
`}
</div>

View file

@ -25,6 +25,7 @@ export class VibeTerminalBuffer extends LitElement {
@state() private error: string | null = null;
@state() private displayedFontSize = 14;
@state() private visibleRows = 0;
@state() private containsEscPrompt = false;
private container: HTMLElement | null = null;
private resizeObserver: ResizeObserver | null = null;
@ -122,6 +123,9 @@ export class VibeTerminalBuffer extends LitElement {
this.buffer = snapshot;
this.error = null;
// Check if buffer contains "esc to interrupt" text
this.checkForEscPrompt();
// Recalculate dimensions now that we have the actual cols
this.calculateDimensions();
@ -130,6 +134,35 @@ export class VibeTerminalBuffer extends LitElement {
});
}
private checkForEscPrompt() {
if (!this.buffer) {
this.containsEscPrompt = false;
return;
}
// Check if any line contains "esc to interrupt" (case insensitive)
const searchText = 'esc to interrupt';
const found = this.buffer.cells.some((row) => {
const lineText = row
.map((cell) => cell.char)
.join('')
.toLowerCase();
return lineText.includes(searchText);
});
if (found !== this.containsEscPrompt) {
this.containsEscPrompt = found;
// Dispatch event to notify parent
this.dispatchEvent(
new CustomEvent('esc-prompt-change', {
detail: { hasEscPrompt: found },
bubbles: true,
composed: true,
})
);
}
}
private unsubscribeFromBuffer() {
if (this.unsubscribe) {
this.unsubscribe();