diff --git a/index.html b/index.html index 46eca8f14..5db9deb74 100644 --- a/index.html +++ b/index.html @@ -320,7 +320,6 @@ - diff --git a/src/client/components/VideoPromo.ts b/src/client/components/VideoPromo.ts deleted file mode 100644 index 6fa108e8b..000000000 --- a/src/client/components/VideoPromo.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { LitElement, html } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; - -const VIDEO_AD_UNIT_TYPE = "precontent_ad_video"; - -@customElement("video-ad") -export class VideoAd extends LitElement { - @state() - private isVisible: boolean = true; - - @property({ attribute: false }) - onComplete?: () => void; - - @property({ attribute: false }) - onMidpoint?: () => void; - - @property({ attribute: false }) - onAdBlocked?: () => void; - - private adLoadTimeout: ReturnType | null = null; - private rampCheckInterval: ReturnType | null = null; - private rampWaitTimeout: ReturnType | null = null; - private adStarted = false; - - // How long to wait for ad to start before assuming it's blocked - private static readonly AD_LOAD_TIMEOUT_MS = 8000; - - createRenderRoot() { - return this; - } - - connectedCallback() { - super.connectedCallback(); - // Set dimensions on the custom element itself (required by Playwire) - // Playwire requires explicit pixel dimensions, use max-width for responsiveness - this.style.display = "block"; - this.style.width = "100%"; - this.style.maxWidth = "800px"; - this.style.aspectRatio = "16/9"; - this.showVideoAd(); - } - - disconnectedCallback() { - super.disconnectedCallback(); - // Clean up timeout if component is removed - if (this.adLoadTimeout) { - clearTimeout(this.adLoadTimeout); - this.adLoadTimeout = null; - } - if (this.rampCheckInterval) { - clearInterval(this.rampCheckInterval); - this.rampCheckInterval = null; - } - if (this.rampWaitTimeout) { - clearTimeout(this.rampWaitTimeout); - this.rampWaitTimeout = null; - } - } - - public showVideoAd(): void { - if (!window.ramp) { - // Wait for ramp to be available, but give up after timeout - this.rampCheckInterval = setInterval(() => { - if (window.ramp && window.ramp.que) { - if (this.rampCheckInterval) { - clearInterval(this.rampCheckInterval); - this.rampCheckInterval = null; - } - if (this.rampWaitTimeout) { - clearTimeout(this.rampWaitTimeout); - this.rampWaitTimeout = null; - } - this.loadVideoAd(); - } - }, 100); - - // Stop polling after timeout (e.g. adblocker preventing ramp from loading) - this.rampWaitTimeout = setTimeout(() => { - if (this.rampCheckInterval) { - clearInterval(this.rampCheckInterval); - this.rampCheckInterval = null; - } - console.log("[VideoAd] Ramp SDK never loaded - possible adblocker"); - this.handleAdBlocked(); - }, VideoAd.AD_LOAD_TIMEOUT_MS); - return; - } - - this.loadVideoAd(); - } - - private loadVideoAd(): void { - // Start timeout to detect if ad doesn't load (e.g., due to adblocker) - this.adLoadTimeout = setTimeout(() => { - if (!this.adStarted) { - console.log("[VideoAd] Ad load timeout - possible adblocker detected"); - this.handleAdBlocked(); - } - }, VideoAd.AD_LOAD_TIMEOUT_MS); - - // Set up event listeners when player is ready, chaining any existing handler - const prevOnPlayerReady = window.ramp.onPlayerReady; - window.ramp.onPlayerReady = () => { - if (prevOnPlayerReady) prevOnPlayerReady(); - if (window.Bolt) { - // Listen for ad start to know ad is loading successfully - window.Bolt.on( - VIDEO_AD_UNIT_TYPE, - window.Bolt.BOLT_AD_STARTED ?? "boltAdStarted", - () => { - console.log("[VideoAd] Ad started"); - this.adStarted = true; - // Clear the timeout since ad is playing - if (this.adLoadTimeout) { - clearTimeout(this.adLoadTimeout); - this.adLoadTimeout = null; - } - }, - ); - - window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_AD_COMPLETE, () => { - console.log("[VideoAd] Ad completed"); - this.hideElement(); - }); - - window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_AD_ERROR, () => { - console.log("[VideoAd] Ad error/no fill"); - this.handleAdBlocked(); - }); - - window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_MIDPOINT, () => { - console.log("[VideoAd] Ad midpoint"); - if (this.onMidpoint) { - this.onMidpoint(); - } - }); - - window.Bolt.on( - VIDEO_AD_UNIT_TYPE, - window.Bolt.SHOW_HIDDEN_CONTAINER ?? "showHiddenContainer", - () => { - console.log("[VideoAd] Ad finished"); - this.hideElement(); - }, - ); - } - }; - - // Queue the video ad initialization - window.ramp.que.push(() => { - const pwUnits = [{ type: VIDEO_AD_UNIT_TYPE }]; - - window.ramp - .addUnits(pwUnits) - .then(() => { - window.ramp.displayUnits(); - }) - .catch((e: Error) => { - console.error("[VideoAd] Error adding units:", e); - window.ramp.displayUnits(); - }); - }); - } - - private handleAdBlocked(): void { - // Clear timeout if still pending - if (this.adLoadTimeout) { - clearTimeout(this.adLoadTimeout); - this.adLoadTimeout = null; - } - - // Call the callback if provided - if (this.onAdBlocked) { - this.onAdBlocked(); - } - } - - private hideElement(): void { - this.style.display = "none"; - this.isVisible = false; - // Call the callback if provided - if (this.onComplete) { - this.onComplete(); - } - // Also dispatch event for backwards compatibility - this.dispatchEvent( - new CustomEvent("ad-complete", { - bubbles: true, - composed: true, - }), - ); - } - - render() { - if (!this.isVisible) { - return html``; - } - - // Provide a container for the Playwire video player to render into - // Structure matches Playwire example: wrapper > game-video-ad > precontent-video-location - return html` -
-
-
- `; - } -} diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index fb0c96810..81d12fc79 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -36,7 +36,6 @@ import { ReplayPanel } from "./layers/ReplayPanel"; import { SAMRadiusLayer } from "./layers/SAMRadiusLayer"; import { SettingsModal } from "./layers/SettingsModal"; import { SpawnTimer } from "./layers/SpawnTimer"; -import { SpawnVideoAd } from "./layers/SpawnVideoReward"; import { StructureIconsLayer } from "./layers/StructureIconsLayer"; import { StructureLayer } from "./layers/StructureLayer"; import { TeamStats } from "./layers/TeamStats"; @@ -268,12 +267,6 @@ export function createRenderer( } inGamePromo.game = game; - const spawnVideoAd = document.querySelector("spawn-video-ad") as SpawnVideoAd; - if (!(spawnVideoAd instanceof SpawnVideoAd)) { - console.error("spawn video ad not found"); - } - spawnVideoAd.game = game; - // When updating these layers please be mindful of the order. // Try to group layers by the return value of shouldTransform. // Not grouping the layers may cause excessive calls to context.save() and context.restore(). @@ -320,7 +313,6 @@ export function createRenderer( headsUpMessage, multiTabModal, inGamePromo, - spawnVideoAd, alertFrame, performanceOverlay, ]; diff --git a/src/client/graphics/layers/SpawnVideoReward.ts b/src/client/graphics/layers/SpawnVideoReward.ts deleted file mode 100644 index 028ec89bc..000000000 --- a/src/client/graphics/layers/SpawnVideoReward.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { LitElement, html } from "lit"; -import { customElement, state } from "lit/decorators.js"; -import { crazyGamesSDK } from "src/client/CrazyGamesSDK"; -import { Platform } from "src/client/Platform"; -import { getGamesPlayed } from "src/client/Utils"; -import { GameType } from "src/core/game/Game"; -import { GameView } from "../../../core/game/GameView"; -import "../../components/VideoPromo"; -import { Layer } from "./Layer"; - -@customElement("spawn-video-ad") -export class SpawnVideoAd extends LitElement implements Layer { - public game: GameView; - - @state() private shouldShow = false; - @state() private adComplete = false; - - createRenderRoot() { - return this; - } - - init() { - if ( - !window.adsEnabled || - Platform.isMobileWidth || - crazyGamesSDK.isOnCrazyGames() || - this.game.config().gameConfig().gameType === GameType.Singleplayer || - getGamesPlayed() < 3 // Don't show to new players - ) { - return; - } - this.shouldShow = true; - } - - tick() { - if (this.adComplete) return; - // Hide when spawn phase ends - if (this.shouldShow && !this.game.inSpawnPhase()) { - this.shouldShow = false; - this.requestUpdate(); - } - } - - private handleComplete = () => { - this.adComplete = true; - this.shouldShow = false; - }; - - shouldTransform(): boolean { - return false; - } - - render() { - if (!this.shouldShow || this.adComplete) { - return html``; - } - - return html` -
- -
- `; - } -}