Skip to content

Commit bec5b5f

Browse files
committed
Merge branch 'v29'
2 parents c54c73d + 1eed561 commit bec5b5f

File tree

5 files changed

+95
-12
lines changed

5 files changed

+95
-12
lines changed

resources/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
"canvas_2d_no_gpu": "Canvas 2D (no GPU)"
9292
},
9393
"help_modal": {
94+
"video_tutorial": "Video Tutorial",
95+
"video_tutorial_title": "OpenFront.io Tutorial",
9496
"hotkeys": "Hotkeys",
9597
"table_key": "Key",
9698
"table_action": "Action",

src/client/HelpModal.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { html } from "lit";
2-
import { customElement, state } from "lit/decorators.js";
3-
import { translateText } from "../client/Utils";
2+
import { customElement, query, state } from "lit/decorators.js";
3+
import { translateText, TUTORIAL_VIDEO_URL } from "../client/Utils";
44
import { BaseModal } from "./components/BaseModal";
55
import "./components/Difficulties";
66
import { modalHeader } from "./components/ui/ModalHeader";
@@ -9,6 +9,7 @@ import { TroubleshootingModal } from "./TroubleshootingModal";
99
@customElement("help-modal")
1010
export class HelpModal extends BaseModal {
1111
@state() private keybinds: Record<string, string> = this.getKeybinds();
12+
@query("#tutorial-video-iframe") private videoIframe?: HTMLIFrameElement;
1213

1314
private isKeybindObject(v: unknown): v is { value: string } {
1415
return (
@@ -120,6 +121,47 @@ export class HelpModal extends BaseModal {
120121
[&_p]:text-gray-300 [&_p]:mb-3 [&_strong]:text-white [&_strong]:font-bold
121122
scrollbar-thin scrollbar-thumb-white/20 scrollbar-track-transparent"
122123
>
124+
<!-- Video Tutorial Section -->
125+
<div class="flex items-center gap-3 mb-3">
126+
<div class="text-blue-400">
127+
<svg
128+
xmlns="http://www.w3.org/2000/svg"
129+
class="w-5 h-5"
130+
viewBox="0 0 24 24"
131+
fill="none"
132+
stroke="currentColor"
133+
stroke-width="2"
134+
stroke-linecap="round"
135+
stroke-linejoin="round"
136+
>
137+
<polygon points="5 3 19 12 5 21 5 3"></polygon>
138+
</svg>
139+
</div>
140+
<h3
141+
class="text-xl font-bold uppercase tracking-widest text-white/90"
142+
>
143+
${translateText("help_modal.video_tutorial")}
144+
</h3>
145+
<div
146+
class="flex-1 h-px bg-gradient-to-r from-blue-500/50 to-transparent"
147+
></div>
148+
</div>
149+
<section
150+
class="bg-white/5 rounded-xl border border-white/10 overflow-hidden mb-8"
151+
>
152+
<div class="relative w-full h-0 pb-[56.25%]">
153+
<iframe
154+
id="tutorial-video-iframe"
155+
class="absolute top-0 left-0 w-full h-full"
156+
src="${TUTORIAL_VIDEO_URL}"
157+
title="${translateText("help_modal.video_tutorial_title")}"
158+
frameborder="0"
159+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
160+
allowfullscreen
161+
></iframe>
162+
</div>
163+
</section>
164+
123165
<!-- Troubleshooting Section -->
124166
<div class="flex items-center gap-3 mb-3">
125167
<div class="text-blue-400">
@@ -1200,5 +1242,16 @@ export class HelpModal extends BaseModal {
12001242

12011243
protected onOpen(): void {
12021244
this.keybinds = this.getKeybinds();
1245+
// Restore the video src when modal opens
1246+
if (this.videoIframe) {
1247+
this.videoIframe.src = TUTORIAL_VIDEO_URL;
1248+
}
1249+
}
1250+
1251+
protected onClose(): void {
1252+
// Clear the iframe src to stop video playback
1253+
if (this.videoIframe) {
1254+
this.videoIframe.src = "";
1255+
}
12031256
}
12041257
}

src/client/Utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import IntlMessageFormat from "intl-messageformat";
22
import { MessageType } from "../core/game/Game";
33
import type { LangSelector } from "./LangSelector";
44

5+
export const TUTORIAL_VIDEO_URL = "https://www.youtube.com/embed/EN2oOog3pSs";
6+
57
export function renderDuration(totalSeconds: number): string {
68
if (totalSeconds <= 0) return "0s";
79
const minutes = Math.floor(totalSeconds / 60);

src/client/components/DesktopNavBar.ts

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { LitElement, html } from "lit";
2-
import { customElement } from "lit/decorators.js";
2+
import { customElement, state } from "lit/decorators.js";
3+
import { getGamesPlayed } from "../Utils";
4+
5+
const HELP_SEEN_KEY = "helpSeen";
36

47
@customElement("desktop-nav-bar")
58
export class DesktopNavBar extends LitElement {
9+
@state() private _helpSeen = localStorage.getItem(HELP_SEEN_KEY) === "true";
10+
611
createRenderRoot() {
712
return this;
813
}
@@ -40,6 +45,15 @@ export class DesktopNavBar extends LitElement {
4045
});
4146
}
4247

48+
private showHelpDot(): boolean {
49+
return getGamesPlayed() < 10 && !this._helpSeen;
50+
}
51+
52+
private onHelpClick = () => {
53+
localStorage.setItem(HELP_SEEN_KEY, "true");
54+
this._helpSeen = true;
55+
};
56+
4357
render() {
4458
return html`
4559
<nav
@@ -125,11 +139,24 @@ export class DesktopNavBar extends LitElement {
125139
data-page="page-stats"
126140
data-i18n="main.stats"
127141
></button>
128-
<button
129-
class="nav-menu-item text-white/70 hover:text-blue-500 font-bold tracking-widest uppercase cursor-pointer transition-colors [&.active]:text-blue-500"
130-
data-page="page-help"
131-
data-i18n="main.help"
132-
></button>
142+
<div class="relative">
143+
<button
144+
class="nav-menu-item text-white/70 hover:text-blue-500 font-bold tracking-widest uppercase cursor-pointer transition-colors [&.active]:text-blue-500"
145+
data-page="page-help"
146+
data-i18n="main.help"
147+
@click=${this.onHelpClick}
148+
></button>
149+
${this.showHelpDot()
150+
? html`
151+
<span
152+
class="absolute -top-1 -right-1 w-2 h-2 bg-yellow-400 rounded-full animate-ping"
153+
></span>
154+
<span
155+
class="absolute -top-1 -right-1 w-2 h-2 bg-yellow-400 rounded-full"
156+
></span>
157+
`
158+
: ""}
159+
</div>
133160
<lang-selector></lang-selector>
134161
<button
135162
id="nav-account-button"

src/client/graphics/layers/WinModal.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { LitElement, TemplateResult, html } from "lit";
1+
import { html, LitElement, TemplateResult } from "lit";
22
import { customElement, state } from "lit/decorators.js";
33
import {
44
getGamesPlayed,
55
isInIframe,
66
translateText,
7+
TUTORIAL_VIDEO_URL,
78
} from "../../../client/Utils";
89
import { ColorPalette, Pattern } from "../../../core/CosmeticSchemas";
910
import { EventBus } from "../../../core/EventBus";
@@ -131,9 +132,7 @@ export class WinModal extends LitElement implements Layer {
131132
<div class="relative w-full pb-[56.25%]">
132133
<iframe
133134
class="absolute top-0 left-0 w-full h-full rounded-sm"
134-
src="${this.isVisible
135-
? "https://www.youtube.com/embed/EN2oOog3pSs"
136-
: ""}"
135+
src="${this.isVisible ? TUTORIAL_VIDEO_URL : ""}"
137136
title="YouTube video player"
138137
frameborder="0"
139138
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"

0 commit comments

Comments
 (0)