Skip to content

Commit e6e1ebe

Browse files
committed
Resolve PR #129 generated report conflicts
2 parents 3dc08fc + 3f81845 commit e6e1ebe

87 files changed

Lines changed: 5279 additions & 1542 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
const TEXT_TO_SPEECH_PROFILE_STORAGE_KEY = "gamefoundry.textToSpeech.profiles.v1";
2+
const TEXT_TO_SPEECH_PROFILE_STORE_VERSION = "tts-profile-store-v1";
3+
4+
const DEFAULT_LANGUAGE = "en-US";
5+
const DEFAULT_PROVIDER_KEY = "browser-speech";
6+
const DEFAULT_VOICE_AGE = "adult";
7+
8+
function clampNumber(value, fallback, min, max) {
9+
const numberValue = Number(value);
10+
if (!Number.isFinite(numberValue)) {
11+
return fallback;
12+
}
13+
return Math.min(max, Math.max(min, numberValue));
14+
}
15+
16+
function normalizedText(value, fallback = "") {
17+
const text = String(value || "").trim();
18+
return text || fallback;
19+
}
20+
21+
function slugFromText(value, fallback = "item") {
22+
return normalizedText(value, fallback)
23+
.toLowerCase()
24+
.replace(/[^a-z0-9]+/g, "-")
25+
.replace(/^-+|-+$/g, "") || fallback;
26+
}
27+
28+
function labelFromSlug(value, fallback = "Neutral") {
29+
return normalizedText(value, fallback)
30+
.replace(/[-_]+/g, " ")
31+
.replace(/\b\w/g, (letter) => letter.toUpperCase());
32+
}
33+
34+
function defaultStorage() {
35+
try {
36+
return typeof window === "undefined" ? null : window.localStorage;
37+
} catch {
38+
return null;
39+
}
40+
}
41+
42+
function storagePayloadProfiles(payload) {
43+
if (Array.isArray(payload)) {
44+
return payload;
45+
}
46+
if (Array.isArray(payload?.profiles)) {
47+
return payload.profiles;
48+
}
49+
return [];
50+
}
51+
52+
function normalizeSavedEmotion(emotion = {}) {
53+
const emotionKey = slugFromText(emotion.emotion || emotion.id || emotion.emotionLabel, "neutral");
54+
const emotionLabel = normalizedText(emotion.emotionLabel || emotion.name, labelFromSlug(emotionKey));
55+
return {
56+
active: emotion.active !== false,
57+
emotion: emotionKey,
58+
emotionLabel,
59+
id: normalizedText(emotion.id, emotionKey),
60+
messagePartsUsageCount: Math.max(0, Number(emotion.messagePartsUsageCount) || 0),
61+
pitch: clampNumber(emotion.pitch, 1, 0.1, 2),
62+
rate: clampNumber(emotion.rate, 1, 0.1, 2),
63+
ssmlLikePreset: normalizedText(emotion.ssmlLikePreset, "normal"),
64+
volume: clampNumber(emotion.volume, 1, 0, 1),
65+
};
66+
}
67+
68+
function normalizeSavedProfile(profile = {}) {
69+
const name = normalizedText(profile.name, "Default Balanced Profile");
70+
const emotions = Array.isArray(profile.emotions) && profile.emotions.length
71+
? profile.emotions.map(normalizeSavedEmotion)
72+
: [normalizeSavedEmotion()];
73+
return {
74+
active: profile.active !== false,
75+
age: normalizedText(profile.age, DEFAULT_VOICE_AGE),
76+
emotions,
77+
gender: normalizedText(profile.gender, "neutral"),
78+
id: normalizedText(profile.id, slugFromText(name, "tts-profile")),
79+
language: normalizedText(profile.language, DEFAULT_LANGUAGE),
80+
messageStudioUsageCount: Math.max(0, Number(profile.messageStudioUsageCount) || 0),
81+
name,
82+
owner: "Audio",
83+
providerKey: normalizedText(profile.providerKey, DEFAULT_PROVIDER_KEY),
84+
voice: normalizedText(profile.voice),
85+
voiceName: normalizedText(profile.voiceName || profile.voice, "Default browser voice"),
86+
};
87+
}
88+
89+
function normalizeSavedTextToSpeechProfiles(profiles = []) {
90+
return Array.isArray(profiles) ? profiles.map(normalizeSavedProfile) : [];
91+
}
92+
93+
function readSavedTextToSpeechProfiles(storage = defaultStorage()) {
94+
if (!storage || typeof storage.getItem !== "function") {
95+
return [];
96+
}
97+
const raw = storage.getItem(TEXT_TO_SPEECH_PROFILE_STORAGE_KEY);
98+
if (!raw) {
99+
return [];
100+
}
101+
let payload;
102+
try {
103+
payload = JSON.parse(raw);
104+
} catch {
105+
throw new Error("Saved Text To Speech profiles could not be read.");
106+
}
107+
return normalizeSavedTextToSpeechProfiles(storagePayloadProfiles(payload));
108+
}
109+
110+
function writeSavedTextToSpeechProfiles(profiles = [], storage = defaultStorage()) {
111+
if (!storage || typeof storage.setItem !== "function") {
112+
return false;
113+
}
114+
const payload = {
115+
profiles: normalizeSavedTextToSpeechProfiles(profiles),
116+
updatedAt: new Date().toISOString(),
117+
version: TEXT_TO_SPEECH_PROFILE_STORE_VERSION,
118+
};
119+
storage.setItem(TEXT_TO_SPEECH_PROFILE_STORAGE_KEY, JSON.stringify(payload));
120+
return true;
121+
}
122+
123+
function textToSpeechProfilesToMessageOptions(profiles = []) {
124+
return normalizeSavedTextToSpeechProfiles(profiles)
125+
.filter((profile) => profile.active !== false)
126+
.map((profile) => ({
127+
active: true,
128+
age: profile.age,
129+
ageFilter: profile.age,
130+
emotionSettings: profile.emotions
131+
.filter((emotion) => emotion.active !== false)
132+
.map((emotion) => ({
133+
active: true,
134+
emotion: emotion.emotion,
135+
emotionLabel: emotion.emotionLabel,
136+
key: emotion.id,
137+
pitch: emotion.pitch,
138+
rate: emotion.rate,
139+
ssmlLikePreset: emotion.ssmlLikePreset,
140+
volume: emotion.volume,
141+
})),
142+
gender: profile.gender,
143+
key: profile.id,
144+
language: profile.language,
145+
name: profile.name,
146+
providerKey: profile.providerKey,
147+
sourceProfileId: profile.id,
148+
voice: profile.voice,
149+
voiceName: profile.voiceName || profile.voice || "Default browser voice",
150+
}));
151+
}
152+
153+
export {
154+
TEXT_TO_SPEECH_PROFILE_STORAGE_KEY,
155+
TEXT_TO_SPEECH_PROFILE_STORE_VERSION,
156+
normalizeSavedTextToSpeechProfiles,
157+
readSavedTextToSpeechProfiles,
158+
textToSpeechProfilesToMessageOptions,
159+
writeSavedTextToSpeechProfiles,
160+
};

assets/theme-v2/css/layout.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ body.tool-focus-mode .tool-workspace--table-scroll-focus .tool-table-scroll-regi
733733
.footer {
734734
margin-top: var(--space-46);
735735
border-top: var(--border-standard);
736-
padding: var(--space-24) var(--space-0);
736+
padding: var(--space-0) var(--space-0) var(--space-24);
737737
color: var(--muted)
738738
}
739739

assets/theme-v2/css/status.css

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@
3636
}
3737

3838
.toolbox-status-bar {
39+
--toolbox-status-bar-height: var(--space-52);
40+
--toolbox-status-game-max: 220px;
3941
width: 100%;
42+
min-block-size: var(--toolbox-status-bar-height);
4043
border-block: var(--border-standard);
4144
background: var(--panel-overlay-strong);
4245
color: var(--text)
@@ -47,7 +50,7 @@
4750
margin: var(--space-0) auto;
4851
padding: var(--space-10) var(--space-0);
4952
display: grid;
50-
grid-template-columns: minmax(var(--space-0), 1fr) minmax(var(--space-0), 2fr);
53+
grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr);
5154
gap: var(--space-16);
5255
align-items: center
5356
}
@@ -56,34 +59,18 @@
5659
min-width: var(--space-0);
5760
display: flex;
5861
align-items: center;
59-
flex-wrap: wrap;
60-
gap: var(--space-14);
62+
justify-content: flex-start;
6163
text-align: left
6264
}
6365

64-
.toolbox-status-bar__field {
65-
min-width: var(--space-0);
66-
display: grid;
67-
gap: var(--space-3)
68-
}
69-
70-
.toolbox-status-bar__label {
71-
color: var(--muted);
72-
font-size: var(--font-size-xs);
73-
font-weight: var(--font-weight-heavy);
74-
letter-spacing: var(--letter-spacing-kicker);
75-
text-transform: uppercase
76-
}
77-
7866
.toolbox-status-bar__game-name {
7967
color: var(--text);
8068
font-size: var(--font-size-base);
81-
overflow-wrap: anywhere
82-
}
83-
84-
.toolbox-status-bar__purpose {
85-
color: var(--muted);
86-
font-size: var(--font-size-sm);
69+
line-height: var(--line-height-tight);
70+
max-width: min(30vw, var(--toolbox-status-game-max));
71+
overflow: hidden;
72+
text-overflow: ellipsis;
73+
white-space: nowrap;
8774
overflow-wrap: anywhere
8875
}
8976

@@ -92,25 +79,17 @@
9279
display: flex;
9380
align-items: center;
9481
justify-content: center;
95-
flex-wrap: wrap;
96-
gap: var(--space-10);
82+
justify-self: center;
9783
text-align: center
9884
}
9985

100-
.toolbox-status-bar__context-type {
101-
flex: 0 0 auto
102-
}
103-
10486
.toolbox-status-bar__message {
10587
margin: var(--space-0);
10688
max-width: var(--measure-lg);
89+
line-height: var(--line-height-copy);
10790
overflow-wrap: anywhere
10891
}
10992

110-
.toolbox-status-bar__action {
111-
flex: 0 0 auto
112-
}
113-
11493
.toolbox-status-bar[data-selected-game-state="active"] {
11594
border-color: color-mix(in srgb, var(--green) 52%, var(--line))
11695
}
@@ -123,22 +102,6 @@
123102
border-color: color-mix(in srgb, var(--red) 52%, var(--line))
124103
}
125104

126-
.toolbox-status-bar[data-toolbox-status-context-kind="error"] .toolbox-status-bar__context-type {
127-
border-color: color-mix(in srgb, var(--red) 62%, var(--line));
128-
color: var(--red)
129-
}
130-
131-
.toolbox-status-bar[data-toolbox-status-context-kind="warning"] .toolbox-status-bar__context-type,
132-
.toolbox-status-bar[data-toolbox-status-context-kind="validation"] .toolbox-status-bar__context-type {
133-
border-color: var(--gold-border-muted);
134-
color: var(--gold)
135-
}
136-
137-
.toolbox-status-bar[data-toolbox-status-context-kind="save"] .toolbox-status-bar__context-type {
138-
border-color: color-mix(in srgb, var(--green) 62%, var(--line));
139-
color: var(--green)
140-
}
141-
142105
body.tool-focus-mode .toolbox-status-bar {
143106
position: fixed;
144107
inset-block-end: var(--space-0);
@@ -148,6 +111,31 @@ body.tool-focus-mode .toolbox-status-bar {
148111
box-shadow: var(--shadow-md)
149112
}
150113

114+
body.tool-focus-mode {
115+
--toolbox-status-bar-height: var(--space-52);
116+
--toolbox-status-top-reserve: var(--space-0)
117+
}
118+
119+
body.tool-focus-mode:has(.platform-banner) {
120+
--toolbox-status-top-reserve: var(--space-52)
121+
}
122+
123+
body.tool-focus-mode .tool-workspace {
124+
box-sizing: border-box;
125+
height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve));
126+
max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve))
127+
}
128+
129+
body.tool-focus-mode .tool-column {
130+
height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20));
131+
max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20))
132+
}
133+
134+
body.tool-focus-mode .tool-center-panel {
135+
box-sizing: border-box;
136+
scroll-padding-block-end: var(--toolbox-status-bar-height)
137+
}
138+
151139
.platform-banner {
152140
width: 100%;
153141
border-bottom: var(--border-standard);
@@ -261,12 +249,16 @@ body.tool-focus-mode .toolbox-status-bar {
261249
@media (max-width: 720px) {
262250
.toolbox-status-bar__inner {
263251
width: var(--container-width);
264-
grid-template-columns: 1fr;
252+
grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr);
253+
gap: var(--space-10);
265254
text-align: center
266255
}
267256

268-
.toolbox-status-bar__game {
269-
justify-content: center;
270-
text-align: center
257+
.toolbox-status-bar__game-name {
258+
max-width: 34vw
259+
}
260+
261+
.toolbox-status-bar__message {
262+
font-size: var(--font-size-sm)
271263
}
272264
}

0 commit comments

Comments
 (0)