mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
feat: client side game strings
This commit is contained in:
1 parent
2d282a3261
commit
f5f3f70e35
7 files changed
+60
-13
No files matched your search
@@ -1,3 +1,5 @@
|
|||||||
|
import { api } from "../../core/api/dynamic";
|
||||||
|
import { useAwait } from "../../hooks/useAwait";
|
||||||
import type { Avatar } from "../../protos/avatar";
|
import type { Avatar } from "../../protos/avatar";
|
||||||
import { Text } from "../Text";
|
import { Text } from "../Text";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
@@ -7,13 +9,22 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function AvatarCard({ avatar }: Props) {
|
export function AvatarCard({ avatar }: Props) {
|
||||||
|
// const { locale } = useLocale();
|
||||||
|
const { locale } = { locale: "en" };
|
||||||
|
const profileAvatarEntityStrings = useAwait(
|
||||||
|
() => api.groupedGameStrings(locale, "ProfileAvatarEntity"),
|
||||||
|
"profile-avatar-entity-strings"
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="avatar-card">
|
<div className="avatar-card">
|
||||||
<div
|
<div
|
||||||
className="avatar-image"
|
className="avatar-image"
|
||||||
style={{ backgroundImage: `url(/api/avatars/${avatar.name}.webp)` }}
|
style={{ backgroundImage: `url(/api/avatars/${avatar.name}.webp)` }}
|
||||||
/>
|
/>
|
||||||
<Text className="avatar-label">{avatar.name}</Text>
|
<Text align="center" className="avatar-label">
|
||||||
|
{profileAvatarEntityStrings[avatar.stuff_ui!.display_name]}
|
||||||
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
&[data-size="minor"] {
|
&[data-size="minor"] {
|
||||||
font-size: var(--font-size-minor);
|
font-size: var(--font-size-minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-size="major"] {
|
&[data-size="major"] {
|
||||||
font-size: var(--font-size-major);
|
font-size: var(--font-size-major);
|
||||||
}
|
}
|
||||||
@@ -12,20 +11,23 @@
|
|||||||
&[data-weight="light"] {
|
&[data-weight="light"] {
|
||||||
font-weight: var(--weight-light);
|
font-weight: var(--weight-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-weight="regular"] {
|
&[data-weight="regular"] {
|
||||||
font-weight: var(--weight-regular);
|
font-weight: var(--weight-regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-weight="medium"] {
|
&[data-weight="medium"] {
|
||||||
font-weight: var(--weight-medium);
|
font-weight: var(--weight-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-weight="bold"] {
|
&[data-weight="bold"] {
|
||||||
font-weight: var(--weight-bold);
|
font-weight: var(--weight-bold);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-weight="black"] {
|
&[data-weight="black"] {
|
||||||
font-weight: var(--weight-black);
|
font-weight: var(--weight-black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[data-align="center"] {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&[data-align="right"] {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ export interface TextProps extends ComponentProps<"span"> {
|
|||||||
weight?: "light" | "regular" | "medium" | "bold" | "black";
|
weight?: "light" | "regular" | "medium" | "bold" | "black";
|
||||||
lowContrast?: boolean;
|
lowContrast?: boolean;
|
||||||
size?: "regular" | "minor" | "major";
|
size?: "regular" | "minor" | "major";
|
||||||
|
align?: "left" | "center" | "right";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Text({
|
export function Text({
|
||||||
@@ -17,6 +18,7 @@ export function Text({
|
|||||||
size = "regular",
|
size = "regular",
|
||||||
weight,
|
weight,
|
||||||
style,
|
style,
|
||||||
|
align,
|
||||||
...props
|
...props
|
||||||
}: TextProps) {
|
}: TextProps) {
|
||||||
return (
|
return (
|
||||||
@@ -25,6 +27,7 @@ export function Text({
|
|||||||
style={{ color: `var(--${color}-${lowContrast ? 11 : 12})`, ...style }}
|
style={{ color: `var(--${color}-${lowContrast ? 11 : 12})`, ...style }}
|
||||||
data-size={size}
|
data-size={size}
|
||||||
data-weight={weight}
|
data-weight={weight}
|
||||||
|
data-align={align === "left" ? undefined : align}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -83,9 +83,10 @@ export abstract class AbstractAPI {
|
|||||||
> = {};
|
> = {};
|
||||||
protected abstract _groupedGameStrings(
|
protected abstract _groupedGameStrings(
|
||||||
locale: string,
|
locale: string,
|
||||||
group: string
|
group: string,
|
||||||
|
prefix: boolean
|
||||||
): Promise<Record<string, string>>;
|
): Promise<Record<string, string>>;
|
||||||
async groupedGameStrings(locale: string, group: string) {
|
async groupedGameStrings(locale: string, group: string, prefix = true) {
|
||||||
this.assertLocale(locale);
|
this.assertLocale(locale);
|
||||||
|
|
||||||
if (this._groupedGameStringsCache[locale] === undefined) {
|
if (this._groupedGameStringsCache[locale] === undefined) {
|
||||||
@@ -94,7 +95,7 @@ export abstract class AbstractAPI {
|
|||||||
|
|
||||||
if (this._groupedGameStringsCache[locale][group] === undefined) {
|
if (this._groupedGameStringsCache[locale][group] === undefined) {
|
||||||
this._groupedGameStringsCache[locale][group] =
|
this._groupedGameStringsCache[locale][group] =
|
||||||
await this._groupedGameStrings(locale, group);
|
await this._groupedGameStrings(locale, group, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._groupedGameStringsCache[locale][group];
|
return this._groupedGameStringsCache[locale][group];
|
||||||
|
|||||||
@@ -6,4 +6,27 @@ export class ClientAPI extends AbstractAPI {
|
|||||||
protected _avatars() {
|
protected _avatars() {
|
||||||
return fetchPB("/api/avatars/all.pb", Avatars);
|
return fetchPB("/api/avatars/all.pb", Avatars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _gameStrings(): Promise<Record<string, string>> {
|
||||||
|
throw new Error("Cannot fetch full game strings on client");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async _groupedGameStrings(
|
||||||
|
locale: string,
|
||||||
|
group: string,
|
||||||
|
prefix: boolean
|
||||||
|
) {
|
||||||
|
const response = await fetch(`/api/game-strings/${locale}/${group}.json`);
|
||||||
|
const json = (await response.json()) as Record<string, string>;
|
||||||
|
|
||||||
|
if (!prefix) return json;
|
||||||
|
|
||||||
|
const strings: Record<string, string> = {};
|
||||||
|
|
||||||
|
for (const key in json) {
|
||||||
|
strings[`${group}__${key}`] = json[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -101,14 +101,17 @@ export class ServerAPI extends AbstractAPI {
|
|||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _groupedGameStrings(locale: string, group: string) {
|
protected async _groupedGameStrings(
|
||||||
|
locale: string,
|
||||||
|
group: string,
|
||||||
|
prefix: boolean
|
||||||
|
) {
|
||||||
const strings = await this.gameStrings(locale);
|
const strings = await this.gameStrings(locale);
|
||||||
const filtered: Record<string, string> = {};
|
const filtered: Record<string, string> = {};
|
||||||
|
|
||||||
for (const key in strings) {
|
for (const key in strings) {
|
||||||
if (key.startsWith(`${group}__`)) {
|
if (key.startsWith(`${group}__`)) {
|
||||||
const trimmed = key.substring(group.length + 2);
|
filtered[prefix ? key : key.substring(group.length + 2)] = strings[key];
|
||||||
filtered[trimmed] = strings[key];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ export async function GET({
|
|||||||
}: {
|
}: {
|
||||||
params: { locale: string; group: string };
|
params: { locale: string; group: string };
|
||||||
}) {
|
}) {
|
||||||
const strings = await api.groupedGameStrings(params.locale, params.group);
|
const strings = await api.groupedGameStrings(
|
||||||
|
params.locale,
|
||||||
|
params.group,
|
||||||
|
false
|
||||||
|
);
|
||||||
return Response.json(strings);
|
return Response.json(strings);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user