mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-19 12:58:09 +00:00
momentModal styling, making speech search fire and forget
Speech creation was holding up the queue, as the promise only resolved when the speech was returned. Made it fire and forget with a toggle to the gameState.isSpeaking to make sure we wait until the turn ends.
This commit is contained in:
parent
79a2eceef4
commit
fe18f5ee52
4 changed files with 59 additions and 41 deletions
|
|
@ -204,25 +204,6 @@ export function closeMomentModal(immediate: boolean = false): void {
|
||||||
function createDialogueOverlay(): HTMLElement {
|
function createDialogueOverlay(): HTMLElement {
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.id = 'dialogue-overlay';
|
overlay.id = 'dialogue-overlay';
|
||||||
overlay.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 1000;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Trigger fade in
|
|
||||||
// Trigger fade in with a small timeout
|
|
||||||
setTimeout(() => overlay.style.opacity = '1', 10);
|
|
||||||
|
|
||||||
return overlay;
|
return overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,24 +212,11 @@ function createDialogueOverlay(): HTMLElement {
|
||||||
*/
|
*/
|
||||||
function createDialogueContainer(power1: string, power2: string, title?: string, moment?: Moment): HTMLElement {
|
function createDialogueContainer(power1: string, power2: string, title?: string, moment?: Moment): HTMLElement {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.className = 'dialogue-container';
|
container.className = "dialogue-container"
|
||||||
container.style.cssText = `
|
|
||||||
background: radial-gradient(ellipse at center, #f7ecd1 0%, #dbc08w8px;
|
|
||||||
box-shadow: 0 0 15px rgba(0,0,0,0.5);
|
|
||||||
width: 90%;
|
|
||||||
height: 85%;
|
|
||||||
position: relative;
|
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Create header section with title and moment info
|
// Create header section with title and moment info
|
||||||
const headerSection = document.createElement('div');
|
const headerSection = document.createElement('div');
|
||||||
headerSection.style.cssText = `
|
headerSection.id = "dialogue-header"
|
||||||
margin-bottom: 15px;
|
|
||||||
text-align: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Add main title
|
// Add main title
|
||||||
const titleElement = document.createElement('h2');
|
const titleElement = document.createElement('h2');
|
||||||
|
|
@ -267,7 +235,7 @@ function createDialogueContainer(power1: string, power2: string, title?: string,
|
||||||
const momentTypeElement = document.createElement('div');
|
const momentTypeElement = document.createElement('div');
|
||||||
momentTypeElement.textContent = `${moment.category} (Interest: ${moment.interest_score}/10)`;
|
momentTypeElement.textContent = `${moment.category} (Interest: ${moment.interest_score}/10)`;
|
||||||
momentTypeElement.style.cssText = `
|
momentTypeElement.style.cssText = `
|
||||||
background: rgba(75, 59, 22, 0.8);
|
background: rgba(75, 59, 22);
|
||||||
color: #f7ecd1;
|
color: #f7ecd1;
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
|
@ -344,7 +312,7 @@ function createDiaryBox(power: PowerENUM, diaryContent: string): HTMLElement {
|
||||||
diaryBox.style.cssText = `
|
diaryBox.style.cssText = `
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
background: rgba(255, 255, 255, 0.4);
|
background: rgba(255, 255, 255);
|
||||||
border: 2px solid #8b7355;
|
border: 2px solid #8b7355;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
@ -363,7 +331,7 @@ function createDiaryBox(power: PowerENUM, diaryContent: string): HTMLElement {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background: rgba(75, 59, 22, 0.1);
|
background: rgba(75, 59, 22, 0.8);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-bottom: 1px solid #8b7355;
|
border-bottom: 1px solid #8b7355;
|
||||||
`;
|
`;
|
||||||
|
|
@ -391,7 +359,7 @@ function createDiaryBox(power: PowerENUM, diaryContent: string): HTMLElement {
|
||||||
p.style.cssText = `
|
p.style.cssText = `
|
||||||
margin: 0 0 4px 0;
|
margin: 0 0 4px 0;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
background: ${index % 2 === 0 ? 'rgba(255,255,255,0.2)' : 'transparent'};
|
background: ${index % 2 === 0 ? 'rgba(255,255,255)' : 'transparent'};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
`;
|
`;
|
||||||
contentArea.appendChild(p);
|
contentArea.appendChild(p);
|
||||||
|
|
@ -428,7 +396,7 @@ function createConversationArea(): HTMLElement {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border: 2px solid #8b7355;
|
border: 2px solid #8b7355;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: rgba(255, 255, 255, 0.3);
|
background: rgba(255, 255, 255, 0.8);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ class GameState {
|
||||||
boardName: string
|
boardName: string
|
||||||
currentPower!: PowerENUM
|
currentPower!: PowerENUM
|
||||||
isPlaying: boolean
|
isPlaying: boolean
|
||||||
|
isSpeaking: boolean
|
||||||
audio: GameAudio
|
audio: GameAudio
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -189,6 +190,7 @@ class GameState {
|
||||||
this.boardName = boardName
|
this.boardName = boardName
|
||||||
this.gameId = 0
|
this.gameId = 0
|
||||||
this.isPlaying = false
|
this.isPlaying = false
|
||||||
|
this.isSpeaking = false
|
||||||
this.audio = new GameAudio()
|
this.audio = new GameAudio()
|
||||||
|
|
||||||
this.scene = new THREE.Scene()
|
this.scene = new THREE.Scene()
|
||||||
|
|
@ -244,7 +246,7 @@ class GameState {
|
||||||
while (true) {
|
while (true) {
|
||||||
let narrator = this.audio.getNarratorPlayer()
|
let narrator = this.audio.getNarratorPlayer()
|
||||||
|
|
||||||
let narratorFinished = (narrator === null) || narrator.ended
|
let narratorFinished = (narrator === null) || narrator.ended || !this.isSpeaking
|
||||||
if (this.unitAnimations.length === 0 && narratorFinished) {
|
if (this.unitAnimations.length === 0 && narratorFinished) {
|
||||||
this.phaseIndex = phaseIdx
|
this.phaseIndex = phaseIdx
|
||||||
updateMapOwnership()
|
updateMapOwnership()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
import { ScheduledEvent } from "./events";
|
import { ScheduledEvent } from "./events";
|
||||||
import { GamePhase } from "./types/gameState";
|
import { GamePhase } from "./types/gameState";
|
||||||
|
import { gameState } from "./gameState";
|
||||||
// TODO: We need to get these pieces of audio ahead of time, instead of paying for them each time we load the front end
|
// TODO: We need to get these pieces of audio ahead of time, instead of paying for them each time we load the front end
|
||||||
// These pieces of audio are predetermined.
|
// These pieces of audio are predetermined.
|
||||||
|
|
||||||
|
|
@ -63,7 +64,18 @@ async function testElevenLabsKey() {
|
||||||
|
|
||||||
export function createNarratorAudioEvent(phase: GamePhase): ScheduledEvent {
|
export function createNarratorAudioEvent(phase: GamePhase): ScheduledEvent {
|
||||||
|
|
||||||
return new ScheduledEvent(`narratorSpeech-${phase.name}`, () => speakSummary(phase.summary))
|
return new ScheduledEvent(`narratorSpeech-${phase.name}`, () => {
|
||||||
|
// Immediately set isSpeaking flag and resolve promise
|
||||||
|
gameState.isSpeaking = true;
|
||||||
|
|
||||||
|
// Start audio generation in background (don't wait for it)
|
||||||
|
speakSummary(phase.summary).finally(() => {
|
||||||
|
gameState.isSpeaking = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resolve immediately so event queue can continue
|
||||||
|
return Promise.resolve();
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -903,3 +903,39 @@
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------
|
||||||
|
Moment Model
|
||||||
|
----------------- */
|
||||||
|
#dialogue-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
.dialogue-container {
|
||||||
|
background: radial-gradient(ellipse at center, #f7ecd1 0%, #dbc08c 100%);
|
||||||
|
border: 3px solid #4f3b16;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 15px rgba(0,0,0,0.5);
|
||||||
|
width: 90%;
|
||||||
|
height: 85%;
|
||||||
|
position: relative;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#dialogue-header {
|
||||||
|
|
||||||
|
margin-bottom: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue