Spaces:
Running
Running
<mat-card class="realtime-chat-container"> | |
<mat-card-header> | |
<mat-icon mat-card-avatar>voice_chat</mat-icon> | |
<mat-card-title>Real-time Conversation</mat-card-title> | |
<mat-card-subtitle> | |
<mat-chip-listbox> | |
<mat-chip [class.active]="currentState === state" | |
*ngFor="let state of conversationStates"> | |
{{ getStateLabel(state) }} | |
</mat-chip> | |
</mat-chip-listbox> | |
</mat-card-subtitle> | |
<button mat-icon-button class="close-button" (click)="closeDialog()"> | |
<mat-icon>close</mat-icon> | |
</button> | |
</mat-card-header> | |
<mat-divider></mat-divider> | |
<mat-card-content> | |
<!-- Error State --> | |
<div class="error-banner" *ngIf="error"> | |
<mat-icon>error_outline</mat-icon> | |
<span>{{ error }}</span> | |
<button mat-icon-button (click)="retryConnection()"> | |
<mat-icon>refresh</mat-icon> | |
</button> | |
</div> | |
<!-- Chat Messages --> | |
<div class="chat-messages" #scrollContainer> | |
<div *ngFor="let msg of messages; trackBy: trackByIndex" | |
[class]="'message ' + msg.role"> | |
<mat-icon class="message-icon"> | |
{{ msg.role === 'user' ? 'person' : msg.role === 'assistant' ? 'smart_toy' : 'info' }} | |
</mat-icon> | |
<div class="message-content"> | |
<div class="message-text">{{ msg.text }}</div> | |
<div class="message-time">{{ msg.timestamp | date:'HH:mm:ss' }}</div> | |
<button *ngIf="msg.audioUrl && msg.role === 'assistant'" | |
mat-icon-button | |
(click)="playAudio(msg.audioUrl)" | |
class="audio-button" | |
[disabled]="isPlayingAudio"> | |
<mat-icon>{{ isPlayingAudio ? 'stop' : 'volume_up' }}</mat-icon> | |
</button> | |
</div> | |
</div> | |
<!-- Empty State --> | |
<div class="empty-state" *ngIf="messages.length === 0 && !isConversationActive"> | |
<mat-icon>mic_off</mat-icon> | |
<p>Konuşmaya başlamak için aşağıdaki butona tıklayın</p> | |
</div> | |
</div> | |
<!-- Audio Visualizer --> | |
<canvas #audioVisualizer | |
class="audio-visualizer" | |
width="600" | |
height="100" | |
[class.active]="isConversationActive"> | |
</canvas> | |
</mat-card-content> | |
<mat-card-actions> | |
<button mat-raised-button | |
color="primary" | |
(click)="toggleConversation()" | |
[disabled]="!sessionId || loading"> | |
@if (loading) { | |
<mat-spinner diameter="20"></mat-spinner> | |
} @else { | |
<mat-icon>{{ isConversationActive ? 'stop' : 'mic' }}</mat-icon> | |
{{ isConversationActive ? 'Konuşmayı Bitir' : 'Konuşmaya Başla' }} | |
} | |
</button> | |
<button mat-button | |
(click)="clearChat()" | |
[disabled]="messages.length === 0"> | |
<mat-icon>clear</mat-icon> | |
Temizle | |
</button> | |
<!-- Barge-in butonu şimdilik gizlendi | |
<button mat-button | |
(click)="performBargeIn()" | |
[disabled]="!isConversationActive || currentState === 'idle' || currentState === 'listening'"> | |
<mat-icon>pan_tool</mat-icon> | |
Kesme (Barge-in) | |
</button> | |
--> | |
</mat-card-actions> | |
</mat-card> |