mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 07:54:20 +00:00
Merge branch 'v25' into v26
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { isInIframe } from "./Utils";
|
||||
|
||||
const LEFT_FUSE = "gutter-ad-container-left";
|
||||
const RIGHT_FUSE = "gutter-ad-container-right";
|
||||
// Minimum screen width to show ads (larger than typical Chromebook)
|
||||
const MIN_SCREEN_WIDTH = 1400;
|
||||
|
||||
@customElement("gutter-ads")
|
||||
export class GutterAds extends LitElement {
|
||||
@state()
|
||||
private isVisible: boolean = false;
|
||||
|
||||
// Override createRenderRoot to disable shadow DOM
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private isScreenLargeEnough(): boolean {
|
||||
return window.innerWidth >= MIN_SCREEN_WIDTH;
|
||||
}
|
||||
|
||||
// Called after the component's DOM is first rendered
|
||||
firstUpdated() {
|
||||
// DOM is guaranteed to be available here
|
||||
console.log("GutterAd DOM is ready");
|
||||
}
|
||||
|
||||
public show(): void {
|
||||
if (!this.isScreenLargeEnough()) {
|
||||
console.log("Screen too small for gutter ads, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInIframe()) {
|
||||
console.log("In iframe, showing gutter ads");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("showing GutterAds");
|
||||
this.isVisible = true;
|
||||
this.requestUpdate();
|
||||
|
||||
// Wait for the update to complete, then load ads
|
||||
this.updateComplete.then(() => {
|
||||
this.loadAds();
|
||||
});
|
||||
}
|
||||
|
||||
public hide(): void {
|
||||
console.log("hiding GutterAds");
|
||||
this.destroyAds();
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private loadAds(): void {
|
||||
// Ensure the container elements exist before loading ads
|
||||
const leftContainer = this.querySelector(`#${LEFT_FUSE}`);
|
||||
const rightContainer = this.querySelector(`#${RIGHT_FUSE}`);
|
||||
|
||||
if (!leftContainer || !rightContainer) {
|
||||
console.warn("Ad containers not found in DOM");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.fusetag) {
|
||||
console.warn("Fuse tag not available");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log("registering zones");
|
||||
window.fusetag.que.push(() => {
|
||||
window.fusetag.registerZone(LEFT_FUSE);
|
||||
window.fusetag.registerZone(RIGHT_FUSE);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to load fuse ads:", error);
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private destroyAds(): void {
|
||||
if (!window.fusetag) {
|
||||
return;
|
||||
}
|
||||
window.fusetag.que.push(() => {
|
||||
window.fusetag.destroyZone(LEFT_FUSE);
|
||||
window.fusetag.destroyZone(RIGHT_FUSE);
|
||||
});
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.destroyAds();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.isVisible) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="fixed left-0 top-1/2 -translate-y-1/2 z-10">
|
||||
<div id="${LEFT_FUSE}" data-fuse="lhs_sticky_vrec"></div>
|
||||
</div>
|
||||
<div class="fixed right-0 top-1/2 -translate-y-1/2 z-10">
|
||||
<div id="${RIGHT_FUSE}" data-fuse="rhs_sticky_vrec"></div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import { FlagInput } from "./FlagInput";
|
||||
import { FlagInputModal } from "./FlagInputModal";
|
||||
import { GameStartingModal } from "./GameStartingModal";
|
||||
import "./GoogleAdElement";
|
||||
import { GutterAds } from "./GutterAds";
|
||||
import { HelpModal } from "./HelpModal";
|
||||
import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
|
||||
import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
|
||||
@@ -51,6 +52,12 @@ declare global {
|
||||
newPageView: () => void;
|
||||
};
|
||||
};
|
||||
fusetag: {
|
||||
registerZone: (id: string) => void;
|
||||
destroyZone: (id: string) => void;
|
||||
pageInit: (options?: any) => void;
|
||||
que: Array<() => void>;
|
||||
};
|
||||
ramp: {
|
||||
que: Array<() => void>;
|
||||
passiveMode: boolean;
|
||||
@@ -94,6 +101,8 @@ class Client {
|
||||
private patternsModal: TerritoryPatternsModal;
|
||||
private tokenLoginModal: TokenLoginModal;
|
||||
|
||||
private gutterAds: GutterAds;
|
||||
|
||||
constructor() {}
|
||||
|
||||
initialize(): void {
|
||||
@@ -160,6 +169,11 @@ class Client {
|
||||
}
|
||||
});
|
||||
|
||||
const gutterAds = document.querySelector("gutter-ads");
|
||||
if (!(gutterAds instanceof GutterAds))
|
||||
throw new Error("Missing gutter-ads");
|
||||
this.gutterAds = gutterAds;
|
||||
|
||||
document.addEventListener("join-lobby", this.handleJoinLobby.bind(this));
|
||||
document.addEventListener("leave-lobby", this.handleLeaveLobby.bind(this));
|
||||
document.addEventListener("kick-player", this.handleKickPlayer.bind(this));
|
||||
@@ -432,6 +446,8 @@ class Client {
|
||||
updateSliderProgress(slider);
|
||||
slider.addEventListener("input", () => updateSliderProgress(slider));
|
||||
});
|
||||
|
||||
this.initializeFuseTag();
|
||||
}
|
||||
|
||||
private handleHash() {
|
||||
@@ -598,6 +614,7 @@ class Client {
|
||||
if (startingModal && startingModal instanceof GameStartingModal) {
|
||||
startingModal.show();
|
||||
}
|
||||
this.gutterAds.hide();
|
||||
},
|
||||
() => {
|
||||
this.joinModal.close();
|
||||
@@ -630,6 +647,7 @@ class Client {
|
||||
console.log("leaving lobby, cancelling game");
|
||||
this.gameStop();
|
||||
this.gameStop = null;
|
||||
this.gutterAds.hide();
|
||||
this.publicLobby.leaveLobby();
|
||||
}
|
||||
|
||||
@@ -641,6 +659,29 @@ class Client {
|
||||
this.eventBus.emit(new SendKickPlayerIntentEvent(target));
|
||||
}
|
||||
}
|
||||
|
||||
private initializeFuseTag() {
|
||||
const tryInitFuseTag = (): boolean => {
|
||||
if (window.fusetag && typeof window.fusetag.pageInit === "function") {
|
||||
console.log("initializing fuse tag");
|
||||
window.fusetag.que.push(() => {
|
||||
window.fusetag.pageInit({
|
||||
blockingFuseIds: ["lhs_sticky_vrec", "rhs_sticky_vrec"],
|
||||
});
|
||||
this.gutterAds.show();
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (tryInitFuseTag()) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the client when the DOM is loaded
|
||||
|
||||
@@ -16,7 +16,6 @@ import { FPSDisplay } from "./layers/FPSDisplay";
|
||||
import { FxLayer } from "./layers/FxLayer";
|
||||
import { GameLeftSidebar } from "./layers/GameLeftSidebar";
|
||||
import { GameRightSidebar } from "./layers/GameRightSidebar";
|
||||
import { GutterAdModal } from "./layers/GutterAdModal";
|
||||
import { HeadsUpMessage } from "./layers/HeadsUpMessage";
|
||||
import { Layer } from "./layers/Layer";
|
||||
import { Leaderboard } from "./layers/Leaderboard";
|
||||
@@ -216,14 +215,6 @@ export function createRenderer(
|
||||
}
|
||||
spawnAd.g = game;
|
||||
|
||||
const gutterAdModal = document.querySelector(
|
||||
"gutter-ad-modal",
|
||||
) as GutterAdModal;
|
||||
if (!(gutterAdModal instanceof GutterAdModal)) {
|
||||
console.error("gutter ad modal not found");
|
||||
}
|
||||
gutterAdModal.eventBus = eventBus;
|
||||
|
||||
const alertFrame = document.querySelector("alert-frame") as AlertFrame;
|
||||
if (!(alertFrame instanceof AlertFrame)) {
|
||||
console.error("alert frame not found");
|
||||
@@ -270,7 +261,6 @@ export function createRenderer(
|
||||
headsUpMessage,
|
||||
multiTabModal,
|
||||
spawnAd,
|
||||
gutterAdModal,
|
||||
alertFrame,
|
||||
fpsDisplay,
|
||||
];
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { EventBus, GameEvent } from "../../../core/EventBus";
|
||||
import { getGamesPlayed } from "../../Utils";
|
||||
import { Layer } from "./Layer";
|
||||
|
||||
export class GutterAdModalEvent implements GameEvent {
|
||||
constructor(public readonly isVisible: boolean) {}
|
||||
}
|
||||
|
||||
@customElement("gutter-ad-modal")
|
||||
export class GutterAdModal extends LitElement implements Layer {
|
||||
public eventBus: EventBus;
|
||||
|
||||
@state()
|
||||
private isVisible: boolean = false;
|
||||
|
||||
@state()
|
||||
private adLoaded: boolean = false;
|
||||
|
||||
private leftAdType: string = "left_rail";
|
||||
private rightAdType: string = "right_rail";
|
||||
private leftContainerId: string = "gutter-ad-container-left";
|
||||
private rightContainerId: string = "gutter-ad-container-right";
|
||||
private margin: string = "10px";
|
||||
|
||||
// Override createRenderRoot to disable shadow DOM
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
init() {
|
||||
if (getGamesPlayed() > 1) {
|
||||
this.eventBus.on(GutterAdModalEvent, (event) => {
|
||||
if (event.isVisible) {
|
||||
this.show();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
tick() {}
|
||||
|
||||
static styles = css``;
|
||||
|
||||
// Called after the component's DOM is first rendered
|
||||
firstUpdated() {
|
||||
// DOM is guaranteed to be available here
|
||||
console.log("GutterAdModal DOM is ready");
|
||||
}
|
||||
|
||||
public show(): void {
|
||||
console.log("showing GutterAdModal");
|
||||
this.isVisible = true;
|
||||
this.requestUpdate();
|
||||
|
||||
// Wait for the update to complete, then load ads
|
||||
this.updateComplete.then(() => {
|
||||
this.loadAds();
|
||||
});
|
||||
}
|
||||
|
||||
public hide(): void {
|
||||
console.log("hiding GutterAdModal");
|
||||
this.isVisible = false;
|
||||
this.destroyAds();
|
||||
this.adLoaded = false;
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private loadAds(): void {
|
||||
// Ensure the container elements exist before loading ads
|
||||
const leftContainer = this.querySelector(`#${this.leftContainerId}`);
|
||||
const rightContainer = this.querySelector(`#${this.rightContainerId}`);
|
||||
|
||||
if (!leftContainer || !rightContainer) {
|
||||
console.warn("Ad containers not found in DOM");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.ramp) {
|
||||
console.warn("Playwire RAMP not available");
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.adLoaded) {
|
||||
console.log("Ads already loaded, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
window.ramp.que.push(() => {
|
||||
window.ramp.spaAddAds([
|
||||
{
|
||||
type: this.leftAdType,
|
||||
selectorId: this.leftContainerId,
|
||||
},
|
||||
{
|
||||
type: this.rightAdType,
|
||||
selectorId: this.rightContainerId,
|
||||
},
|
||||
]);
|
||||
this.adLoaded = true;
|
||||
console.log("Playwire ads loaded:", this.leftAdType, this.rightAdType);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to load Playwire ads:", error);
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private destroyAds(): void {
|
||||
if (!window.ramp || !this.adLoaded) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
window.ramp.destroyUnits("all");
|
||||
} catch (error) {
|
||||
console.error("Failed to destroy Playwire ad:", error);
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.destroyAds();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.isVisible) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<!-- Left Gutter Ad -->
|
||||
<div
|
||||
class="hidden xl:flex fixed left-0 top-1/2 transform -translate-y-1/2 w-[160px] min-h-[600px] z-[10] pointer-events-auto items-center justify-center"
|
||||
style="margin-left: ${this.margin};"
|
||||
>
|
||||
<div
|
||||
id="${this.leftContainerId}"
|
||||
class="w-full h-full flex items-center justify-center p-2"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- Right Gutter Ad -->
|
||||
<div
|
||||
class="hidden xl:flex fixed right-0 top-1/2 transform -translate-y-1/2 w-[160px] min-h-[600px] z-[10] pointer-events-auto items-center justify-center"
|
||||
style="margin-right: ${this.margin};"
|
||||
>
|
||||
<div
|
||||
id="${this.rightContainerId}"
|
||||
class="w-full h-full flex items-center justify-center p-2"
|
||||
></div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
+6
-20
@@ -91,12 +91,11 @@
|
||||
document.documentElement.className = "preload";
|
||||
</script>
|
||||
|
||||
<!-- Playwire ads -->
|
||||
<script>
|
||||
window.ramp = window.ramp || {};
|
||||
window.ramp.que = window.ramp.que || [];
|
||||
window.ramp.passiveMode = true;
|
||||
</script>
|
||||
<!-- Publift/Fuse ads -->
|
||||
<script
|
||||
async
|
||||
src="https://cdn.fuseplatform.net/publift/tags/2/4121/fuse.js"
|
||||
></script>
|
||||
|
||||
<!-- Analytics -->
|
||||
<script
|
||||
@@ -197,7 +196,7 @@
|
||||
</header>
|
||||
<div class="bg-image"></div>
|
||||
|
||||
<gutter-ad-modal></gutter-ad-modal>
|
||||
<gutter-ads></gutter-ads>
|
||||
|
||||
<!-- Main container with responsive padding -->
|
||||
<main class="flex justify-center flex-grow">
|
||||
@@ -369,16 +368,6 @@
|
||||
>
|
||||
Terms of Service
|
||||
</a>
|
||||
<p style="text-align: center">
|
||||
<a
|
||||
href="https://www.playwire.com/contact-direct-sales"
|
||||
data-i18n="main.advertise"
|
||||
class="t-link"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Advertise</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -438,9 +427,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Playwire ads -->
|
||||
<script async src="//cdn.intergient.com/1025558/75940/ramp.js"></script>
|
||||
|
||||
<!-- Analytics -->
|
||||
<script
|
||||
defer
|
||||
|
||||
Reference in New Issue
Block a user