From b9973f1277fad9df841abaa0424eff75e8c6de28 Mon Sep 17 00:00:00 2001 From: Miodec Date: Tue, 12 Jul 2022 13:01:26 +0200 Subject: [PATCH] ads --- backend/src/api/schemas/config-schema.ts | 1 + frontend/src/styles/ads.scss | 63 +++++ frontend/src/styles/core.scss | 18 ++ frontend/src/styles/index.scss | 2 +- frontend/src/styles/popups.scss | 39 +++ frontend/src/styles/test.scss | 3 +- frontend/src/styles/z_media-queries.scss | 18 ++ frontend/src/ts/config.ts | 238 +++++++++--------- frontend/src/ts/constants/default-config.ts | 2 +- frontend/src/ts/controllers/ad-controller.ts | 196 +++++++++++++++ .../src/ts/controllers/page-controller.ts | 2 + frontend/src/ts/elements/commandline-lists.ts | 26 +- frontend/src/ts/elements/notifications.ts | 3 + frontend/src/ts/index.ts | 2 + frontend/src/ts/observables/banner-event.ts | 18 ++ frontend/src/ts/pages/settings.ts | 6 +- frontend/src/ts/popups/video-ad-popup.ts | 37 +++ frontend/src/ts/test/focus.ts | 1 + frontend/src/ts/test/result.ts | 2 + frontend/src/ts/test/test-logic.ts | 2 + frontend/src/ts/types/types.d.ts | 4 +- frontend/static/html/pages/about.html | 18 +- frontend/static/html/pages/account.html | 17 +- frontend/static/html/pages/settings.html | 52 ++-- frontend/static/html/pages/test.html | 17 ++ frontend/static/html/popups.html | 21 +- frontend/static/main.html | 34 ++- 27 files changed, 671 insertions(+), 171 deletions(-) create mode 100644 frontend/src/styles/ads.scss create mode 100644 frontend/src/ts/controllers/ad-controller.ts create mode 100644 frontend/src/ts/observables/banner-event.ts create mode 100644 frontend/src/ts/popups/video-ad-popup.ts diff --git a/backend/src/api/schemas/config-schema.ts b/backend/src/api/schemas/config-schema.ts index 98db9a2f3..fbe038937 100644 --- a/backend/src/api/schemas/config-schema.ts +++ b/backend/src/api/schemas/config-schema.ts @@ -87,6 +87,7 @@ const CONFIG_SCHEMA = joi.object({ tapeMode: joi.string().valid("off", "letter", "word"), alwaysShowCPM: joi.boolean(), enableAds: joi.string().valid("off", "on", "max"), + ads: joi.string().valid("off", "result", "on", "sellout"), hideExtraLetters: joi.boolean(), strictSpace: joi.boolean(), minAcc: joi.string().valid("off", "custom"), diff --git a/frontend/src/styles/ads.scss b/frontend/src/styles/ads.scss new file mode 100644 index 000000000..46e502dcf --- /dev/null +++ b/frontend/src/styles/ads.scss @@ -0,0 +1,63 @@ +#ad-vertical-left-wrapper, +#ad-vertical-right-wrapper { + margin-top: 2rem; + transition: margin-top 0.125s; +} + +#ad-footer-wrapper, +#ad-footer-small-wrapper { + justify-self: center; +} + +#ad-result-wrapper, +#ad-result-small-wrapper, +.pageSettings .ad, +.pageAbout .ad, +.pageAccount .ad { + margin: 1rem auto 0 auto; +} + +#app.focus { + .ad { + display: none; + } +} + +.ad { + background: var(--sub-alt-color); + display: grid; + grid-template-areas: "col"; + + div { + grid-area: col; + } + + .icon { + font-size: 3rem; + height: 100%; + width: 100%; + display: grid; + justify-content: center; + align-items: center; + color: var(--sub-color); + &.small { + font-size: 1.5rem; + } + } + + &.ad-v { + width: 160px; + height: 600px; + } + + &.ad-h { + width: 728px; + height: 90px; + } + + &.ad-h-s { + width: 320px; + height: 50px; + display: none; + } +} diff --git a/frontend/src/styles/core.scss b/frontend/src/styles/core.scss index 9b920afb6..855d9415b 100644 --- a/frontend/src/styles/core.scss +++ b/frontend/src/styles/core.scss @@ -35,6 +35,24 @@ /* Firefox */ } +#app { + display: grid; + grid-template-columns: auto minmax(0, 1000px) auto; + justify-items: center; + &.wide125 { + grid-template-columns: auto minmax(0, 1250px) auto; + } + &.wide150 { + grid-template-columns: auto minmax(0, 1500px) auto; + } + &.wide200 { + grid-template-columns: auto minmax(0, 2000px) auto; + } + &.widemax { + grid-template-columns: auto minmax(0, 1fr) auto; + } +} + #nocss { display: none !important; pointer-events: none; diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index 9e10e95ad..c37ddf495 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -1,4 +1,4 @@ -@import "404", "about", "account", "animations", "banners", "caret", +@import "404", "ads", "about", "account", "animations", "banners", "caret", "commandline", "core", "footer", "inputs", "keymap", "leaderboards", "login", "monkey", "nav", "notifications", "popups", "profile", "scroll", "settings", "test", "z_media-queries"; diff --git a/frontend/src/styles/popups.scss b/frontend/src/styles/popups.scss index b2ce55c92..372bddf1b 100644 --- a/frontend/src/styles/popups.scss +++ b/frontend/src/styles/popups.scss @@ -479,11 +479,50 @@ place-self: center; grid-area: check; } + &.ads { + grid-template-columns: 1fr; + grid-template-areas: + "title" + "description"; + a { + margin-top: 0.25rem; + } + } } } } } +#videoAdPopupWrapper { + display: flex; + padding: 2rem; + #videoAdPopup { + background: var(--bg-color); + border-radius: var(--roundness); + padding: 2rem; + display: grid; + gap: 1rem; + width: 100%; + max-width: 1000px; + aspect-ratio: 16/9; + display: grid; + grid-template-areas: "middle"; + .preloader { + grid-area: middle; + display: grid; + place-items: center center; + gap: 1rem; + font-size: 2rem; + color: var(--main-color); + height: max-content; + align-self: center; + } + .video { + grid-area: middle; + } + } +} + #pbTablesPopupWrapper #pbTablesPopup { .title { color: var(--text-color); diff --git a/frontend/src/styles/test.scss b/frontend/src/styles/test.scss index 4671e0e7c..1e28d525c 100644 --- a/frontend/src/styles/test.scss +++ b/frontend/src/styles/test.scss @@ -883,7 +883,8 @@ #restartTestButtonWithSameWordset, #nextTestButton, #practiseWordsButton, -#watchReplayButton { +#watchReplayButton, +#watchVideoAdButton { position: relative; border-radius: var(--roundness); padding: 1rem 2rem; diff --git a/frontend/src/styles/z_media-queries.scss b/frontend/src/styles/z_media-queries.scss index 62512896d..54f259361 100644 --- a/frontend/src/styles/z_media-queries.scss +++ b/frontend/src/styles/z_media-queries.scss @@ -1,3 +1,12 @@ +@media only screen and (max-width: 1330px) { + .ad.ad-v { + display: none; + } + #app { + grid-template-columns: auto; + } +} + @media only screen and (max-width: 1250px) { #leaderboardsWrapper #leaderboards { .mainTitle { @@ -103,6 +112,12 @@ } @media only screen and (max-width: 900px) { + .ad.ad-h { + display: none; + } + .ad.ad-h-s { + display: grid; + } .profile .pbsWords, .profile .pbsTime { font-size: 1rem; @@ -827,6 +842,9 @@ } @media only screen and (max-width: 350px) { + .ad.ad-h-s { + display: none; + } #keymap { display: none !important; } diff --git a/frontend/src/ts/config.ts b/frontend/src/ts/config.ts index f47caeeab..acd5caf5e 100644 --- a/frontend/src/ts/config.ts +++ b/frontend/src/ts/config.ts @@ -542,31 +542,22 @@ export function setQuickEnd(qe: boolean, nosave?: boolean): boolean { return true; } -export function setEnableAds( - val: MonkeyTypes.EnableAds, - nosave?: boolean -): boolean { - if (!isConfigValueValid("enable ads", val, [["on", "off", "max"]])) { +export function setAds(val: MonkeyTypes.Ads, nosave?: boolean): boolean { + if (!isConfigValueValid("ads", val, [["off", "result", "on", "sellout"]])) { return false; } - config.enableAds = "off"; + config.ads = val; + saveToLocalStorage("ads", nosave); if (!nosave) { - saveToLocalStorage("enableAds", nosave); - Notifications.add("Ads have been temporarily disabled", 0); + setTimeout(() => { + location.reload(); + }, 3000); + Notifications.add("Ad settings changed. Refreshing...", 0); } + ConfigEvent.dispatch("ads", config.ads); + return true; - - // config.enableAds = val; - // if (!nosave) { - // saveToLocalStorage("enableAds", nosave); - // setTimeout(() => { - // location.reload(); - // }, 3000); - // Notifications.add("Ad settings changed. Refreshing...", 0); - // } - - // return true; } export function setRepeatQuotes( @@ -652,9 +643,14 @@ export function setPageWidth( $("#centerContent").removeClass("wide150"); $("#centerContent").removeClass("wide200"); $("#centerContent").removeClass("widemax"); + $("#app").removeClass("wide125"); + $("#app").removeClass("wide150"); + $("#app").removeClass("wide200"); + $("#app").removeClass("widemax"); if (val !== "100") { $("#centerContent").addClass("wide" + val); + $("#app").addClass("wide" + val); } saveToLocalStorage("pageWidth", nosave); ConfigEvent.dispatch("pageWidth", config.pageWidth); @@ -1818,120 +1814,122 @@ export function apply( setLazyMode(configObj.lazyMode, true); setShowAverage(configObj.showAverage, true); setTapeMode(configObj.tapeMode, true); + setAds(configObj.ads, true); - try { - setEnableAds(configObj.enableAds, true); + // try { + // setEnableAds(configObj.enableAds, true); - if (config.enableAds === "max" || config.enableAds === "on") { - // $("head").append(` - // - // `); + // if (config.enableAds === "max" || config.enableAds === "on") { + // // $("head").append(` + // // + // // `); - if (config.enableAds === "max") { - // + // if (config.enableAds === "max") { + // // - $("#ad_rich_media").removeClass("hidden"); - $("#ad_rich_media") - .html - // `` - (); - } else { - $("#ad_rich_media").remove(); - } + // $("#ad_rich_media").removeClass("hidden"); + // $("#ad_rich_media") + // .html + // // `` + // (); + // } else { + // $("#ad_rich_media").remove(); + // } - //
+ // //
- $("#ad_footer") - .html - // `
` - (); - $("#ad_footer").removeClass("hidden"); + // $("#ad_footer") + // .html + // // `
` + // (); + // $("#ad_footer").removeClass("hidden"); - // $("#ad_footer2").html(`
`); - // $("#ad_footer2").removeClass("hidden"); + // // $("#ad_footer2").html(`
`); + // // $("#ad_footer2").removeClass("hidden"); - $("#ad_about1") - .html - // `
` - (); - $("#ad_about1").removeClass("hidden"); + // $("#ad_about1") + // .html + // // `
` + // (); + // $("#ad_about1").removeClass("hidden"); - $("#ad_about2") - .html - // `
` - (); - $("#ad_about2").removeClass("hidden"); + // $("#ad_about2") + // .html + // // `
` + // (); + // $("#ad_about2").removeClass("hidden"); - $("#ad_settings0") - .html - // `
` - (); - $("#ad_settings0").removeClass("hidden"); + // $("#ad_settings0") + // .html + // // `
` + // (); + // $("#ad_settings0").removeClass("hidden"); - $("#ad_settings1") - .html - // `
` - (); - $("#ad_settings1").removeClass("hidden"); + // $("#ad_settings1") + // .html + // // `
` + // (); + // $("#ad_settings1").removeClass("hidden"); - $("#ad_settings2") - .html - // `
` - (); - $("#ad_settings2").removeClass("hidden"); + // $("#ad_settings2") + // .html + // // `
` + // (); + // $("#ad_settings2").removeClass("hidden"); - $("#ad_settings3") - .html - // `
` - (); - $("#ad_settings3").removeClass("hidden"); + // $("#ad_settings3") + // .html + // // `
` + // (); + // $("#ad_settings3").removeClass("hidden"); + + // $("#ad_account") + // .html + // // `
` + // (); + // $("#ad_account").removeClass("hidden"); + // $(".footerads").removeClass("hidden"); + // } else { + // $("#adScript").remove(); + // $(".footerads").remove(); + // $("#ad_left").remove(); + // $("#ad_right").remove(); + // $("#ad_footer").remove(); + // $("#ad_footer2").remove(); + // $("#ad_footer3").remove(); + // $("#ad_settings0").remove(); + // $("#ad_settings1").remove(); + // $("#ad_settings2").remove(); + // $("#ad_settings3").remove(); + // $("#ad_account").remove(); + // $("#ad_about1").remove(); + // $("#ad_about2").remove(); + // } + // } catch (e) { + // Notifications.add("Error initialising ads: " + (e as Error).message); + // console.log("error initialising ads " + (e as Error).message); + // $(".footerads").remove(); + // $("#ad_left").remove(); + // $("#ad_right").remove(); + // $("#ad_footer").remove(); + // $("#ad_footer2").remove(); + // $("#ad_footer3").remove(); + // $("#ad_settings0").remove(); + // $("#ad_settings1").remove(); + // $("#ad_settings2").remove(); + // $("#ad_settings3").remove(); + // $("#ad_account").remove(); + // $("#ad_about1").remove(); + // $("#ad_about2").remove(); + // } - $("#ad_account") - .html - // `
` - (); - $("#ad_account").removeClass("hidden"); - $(".footerads").removeClass("hidden"); - } else { - $("#adScript").remove(); - $(".footerads").remove(); - $("#ad_left").remove(); - $("#ad_right").remove(); - $("#ad_footer").remove(); - $("#ad_footer2").remove(); - $("#ad_footer3").remove(); - $("#ad_settings0").remove(); - $("#ad_settings1").remove(); - $("#ad_settings2").remove(); - $("#ad_settings3").remove(); - $("#ad_account").remove(); - $("#ad_about1").remove(); - $("#ad_about2").remove(); - } - } catch (e) { - Notifications.add("Error initialising ads: " + (e as Error).message); - console.log("error initialising ads " + (e as Error).message); - $(".footerads").remove(); - $("#ad_left").remove(); - $("#ad_right").remove(); - $("#ad_footer").remove(); - $("#ad_footer2").remove(); - $("#ad_footer3").remove(); - $("#ad_settings0").remove(); - $("#ad_settings1").remove(); - $("#ad_settings2").remove(); - $("#ad_settings3").remove(); - $("#ad_account").remove(); - $("#ad_about1").remove(); - $("#ad_about2").remove(); - } ConfigEvent.dispatch( "configApplied", undefined, @@ -1967,6 +1965,8 @@ export function loadFromLocalStorage(): void { localStorageConfig = newConfig; saveFullConfigToLocalStorage(true); console.log("saving localStorage config"); + } else { + reset(); } // TestLogic.restart(false, true); loadDone(); diff --git a/frontend/src/ts/constants/default-config.ts b/frontend/src/ts/constants/default-config.ts index 73a8d1d6a..586654d3d 100644 --- a/frontend/src/ts/constants/default-config.ts +++ b/frontend/src/ts/constants/default-config.ts @@ -74,7 +74,7 @@ export default { minWpmCustomSpeed: 100, highlightMode: "letter", alwaysShowCPM: false, - enableAds: "off", + ads: "result", hideExtraLetters: false, strictSpace: false, minAcc: "off", diff --git a/frontend/src/ts/controllers/ad-controller.ts b/frontend/src/ts/controllers/ad-controller.ts new file mode 100644 index 000000000..71cac2224 --- /dev/null +++ b/frontend/src/ts/controllers/ad-controller.ts @@ -0,0 +1,196 @@ +import { debounce } from "throttle-debounce"; +import * as Misc from "../utils/misc"; +import * as ConfigEvent from "../observables/config-event"; +import * as BannerEvent from "../observables/banner-event"; +import Config from "../config"; +import * as TestActive from "../states/test-active"; + +const breakpoint = 900; +let widerThanBreakpoint = true; + +let initialised = false; + +export function init(): void { + $("head").append(``); + $("body") + .prepend(``); + + setInterval(() => { + if (TestActive.get()) { + console.log("test active - stopping ad refresh"); + return; + } + refreshVisible(); + console.log("refreshing visible ads"); + }, 30000); + + initialised = true; +} + +export function removeAll(): void { + removeSellout(); + removeOn(); + removeResult(); +} + +export function removeSellout(): void { + $("#ad-footer-wrapper").remove(); + $("#ad-footer-small-wrapper").remove(); + $("#ad-about-1-wrapper").remove(); + $("#ad-about-1-small-wrapper").remove(); + $("#ad-about-2-wrapper").remove(); + $("#ad-about-2-small-wrapper").remove(); + $("#ad-settings-1-wrapper").remove(); + $("#ad-settings-1-small-wrapper").remove(); + $("#ad-settings-2-wrapper").remove(); + $("#ad-settings-2-small-wrapper").remove(); + $("#ad-settings-3-wrapper").remove(); + $("#ad-settings-3-small-wrapper").remove(); + $("#ad-account-1-wrapper").remove(); + $("#ad-account-1-small-wrapper").remove(); + $("#ad-account-2-wrapper").remove(); + $("#ad-account-2-small-wrapper").remove(); +} + +export function removeOn(): void { + $("#ad-vertical-right-wrapper").remove(); + $("#ad-vertical-left-wrapper").remove(); +} + +export function removeResult(): void { + $("#ad-result-wrapper").remove(); + $("#ad-result-small-wrapper").remove(); +} + +function updateVerticalMargin(): void { + const height = $("#bannerCenter").height() as number; + const margin = height + Misc.convertRemToPixels(2) + "px"; + $("#ad-vertical-left-wrapper").css("margin-top", margin); + $("#ad-vertical-right-wrapper").css("margin-top", margin); +} + +function updateBreakpoint(noReinstate = false): void { + const beforeUpdate = widerThanBreakpoint; + + if (window.innerWidth > breakpoint) { + widerThanBreakpoint = true; + } else { + widerThanBreakpoint = false; + } + if (noReinstate) return; + if (beforeUpdate !== widerThanBreakpoint) { + reinstate(); + } +} + +export async function refreshVisible(): Promise { + //@ts-ignore + const adDivs = Object.keys(window.egAdPack.gptAdSlots); + const visibleAdDivs = []; + + for (let i = 0; i < adDivs.length; i++) { + const el = document.querySelectorAll( + "[data-adunit-name='" + adDivs[i] + "']" + )[0]; + if (!el) continue; + const elParent = el.parentElement as HTMLElement; + if ( + window.getComputedStyle(elParent).getPropertyValue("display") != "none" + ) { + visibleAdDivs.push(adDivs[i]); + } + } + console.log("refreshing", visibleAdDivs); + //@ts-ignore + window.egAps.refreshAds(visibleAdDivs); +} + +export function reinstate(): boolean { + if (Config.ads === "off") return false; + if (!initialised) { + init(); + return true; + } + try { + //@ts-ignore + window.egAps.reinstate(); + return true; + } catch (e) { + console.error(e); + return false; + } +} + +export async function renderResult(): Promise { + if (Config.ads === "off") return; + if (!initialised) { + init(); + } + if (widerThanBreakpoint) { + // $("#ad-result-wrapper").html(` + //
+ //
+ // `); + // if ($("#ad-result-wrapper").is(":empty")) { + //@ts-ignore + // window.egAps.render(["ad-result"]); + // } else { + //@ts-ignore + window.egAps.refreshAds(["ad-result"]); + // } + } else { + // $("#ad-result-small-wrapper").html(` + //
+ //
+ // `); + // if ($("#ad-result-small-wrapper").is(":empty")) { + //@ts-ignore + // window.egAps.render(["ad-result-small"]); + // } else { + //@ts-ignore + window.egAps.refreshAds(["ad-result-small"]); + // } + } +} + +export function destroyResult(): void { + // $("#ad-result-wrapper").empty(); + // $("#ad-result-small-wrapper").empty(); +} + +const debouncedMarginUpdate = debounce(100, updateVerticalMargin); +const debouncedBreakpointUpdate = debounce(100, updateBreakpoint); + +$(window).on("resize", () => { + debouncedMarginUpdate(); + debouncedBreakpointUpdate(); +}); + +ConfigEvent.subscribe((event, value) => { + if (event === "ads") { + if (value == "off") { + removeAll(); + } else if (value == "result") { + removeSellout(); + removeOn(); + } else if (value == "on") { + removeSellout(); + } + } +}); + +BannerEvent.subscribe(() => { + updateVerticalMargin(); +}); + +$(document).ready(() => { + updateBreakpoint(true); +}); diff --git a/frontend/src/ts/controllers/page-controller.ts b/frontend/src/ts/controllers/page-controller.ts index 6ab49b3e8..bcb3ca988 100644 --- a/frontend/src/ts/controllers/page-controller.ts +++ b/frontend/src/ts/controllers/page-controller.ts @@ -10,6 +10,7 @@ import * as PageProfile from "../pages/profile"; import * as Page404 from "../pages/404"; import * as PageTransition from "../states/page-transition"; import type Page from "../pages/page"; +import * as AdController from "../controllers/ad-controller"; export async function change( page: Page, @@ -58,6 +59,7 @@ export async function change( nextPage?.afterShow(); }, async () => { + AdController.reinstate(); await nextPage?.beforeShow(params); } ); diff --git a/frontend/src/ts/elements/commandline-lists.ts b/frontend/src/ts/elements/commandline-lists.ts index dadd74c40..9ac2b2020 100644 --- a/frontend/src/ts/elements/commandline-lists.ts +++ b/frontend/src/ts/elements/commandline-lists.ts @@ -1212,30 +1212,38 @@ const commandsDifficulty: MonkeyTypes.CommandsGroup = { export const commandsEnableAds: MonkeyTypes.CommandsGroup = { title: "Set enable ads...", - configKey: "enableAds", + configKey: "ads", list: [ { id: "setEnableAdsOff", display: "off", configValue: "off", exec: (): void => { - UpdateConfig.setEnableAds("off"); + UpdateConfig.setAds("off"); }, }, { id: "setEnableAdsOn", - display: "on", - configValue: "on", + display: "result", + configValue: "result", exec: (): void => { - UpdateConfig.setEnableAds("on"); + UpdateConfig.setAds("result"); }, }, { - id: "setEnableMax", - display: "sellout", - configValue: "max", + id: "setEnableOn", + display: "on", + configValue: "on", exec: (): void => { - UpdateConfig.setEnableAds("max"); + UpdateConfig.setAds("on"); + }, + }, + { + id: "setEnableSellout", + display: "sellout", + configValue: "sellout", + exec: (): void => { + UpdateConfig.setAds("sellout"); }, }, ], diff --git a/frontend/src/ts/elements/notifications.ts b/frontend/src/ts/elements/notifications.ts index b5c224aba..8117c97a9 100644 --- a/frontend/src/ts/elements/notifications.ts +++ b/frontend/src/ts/elements/notifications.ts @@ -1,5 +1,6 @@ import { debounce } from "throttle-debounce"; import * as Misc from "../utils/misc"; +import * as BannerEvent from "../observables/banner-event"; function updateMargin(): void { console.log("updating margin"); @@ -165,6 +166,7 @@ class Notification { `); updateMargin(); + BannerEvent.dispatch(); if (this.duration >= 0) { $(`#bannerCenter .banner[id='${this.id}'] .closeButton`).on( "click", @@ -213,6 +215,7 @@ class Notification { () => { $(`#bannerCenter .banner[id='${this.id}']`).remove(); updateMargin(); + BannerEvent.dispatch(); } ); } diff --git a/frontend/src/ts/index.ts b/frontend/src/ts/index.ts index c0e905579..ea4b062af 100644 --- a/frontend/src/ts/index.ts +++ b/frontend/src/ts/index.ts @@ -5,6 +5,7 @@ import "./firebase"; import * as DB from "./db"; import "./ui"; +import "./controllers/ad-controller"; import Config from "./config"; import * as TestStats from "./test/test-stats"; import * as Replay from "./test/replay"; @@ -17,6 +18,7 @@ import "./test/caps-warning"; import "./popups/support-popup"; import "./popups/contact-popup"; import "./popups/version-popup"; +import "./popups/video-ad-popup"; import "./popups/edit-preset-popup"; import "./popups/simple-popups"; import "./controllers/input-controller"; diff --git a/frontend/src/ts/observables/banner-event.ts b/frontend/src/ts/observables/banner-event.ts new file mode 100644 index 000000000..6d6b72ccd --- /dev/null +++ b/frontend/src/ts/observables/banner-event.ts @@ -0,0 +1,18 @@ +type SubscribeFunction = () => void; + +const subscribers: SubscribeFunction[] = []; + +export function subscribe(fn: SubscribeFunction): void { + subscribers.push(fn); +} + +export function dispatch(): void { + subscribers.forEach((fn) => { + try { + fn(); + } catch (e) { + console.error("Banner event subscriber threw an error"); + console.error(e); + } + }); +} diff --git a/frontend/src/ts/pages/settings.ts b/frontend/src/ts/pages/settings.ts index f5e318df7..707d3eafe 100644 --- a/frontend/src/ts/pages/settings.ts +++ b/frontend/src/ts/pages/settings.ts @@ -166,11 +166,7 @@ async function initGroups(): Promise { UpdateConfig.setRepeatQuotes, "button" ); - groups["enableAds"] = new SettingsGroup( - "enableAds", - UpdateConfig.setEnableAds, - "button" - ); + groups["ads"] = new SettingsGroup("ads", UpdateConfig.setAds, "button"); groups["alwaysShowWordsHistory"] = new SettingsGroup( "alwaysShowWordsHistory", UpdateConfig.setAlwaysShowWordsHistory, diff --git a/frontend/src/ts/popups/video-ad-popup.ts b/frontend/src/ts/popups/video-ad-popup.ts new file mode 100644 index 000000000..c723c25f1 --- /dev/null +++ b/frontend/src/ts/popups/video-ad-popup.ts @@ -0,0 +1,37 @@ +function show(): void { + if ($("#videoAdPopupWrapper").hasClass("hidden")) { + $("#videoAdPopupWrapper") + .stop(true, true) + .css("opacity", 0) + .removeClass("hidden") + .animate({ opacity: 1 }, 100, () => { + //@ts-ignore + window.dataLayer.push({ event: "EG_Video" }); + }); + } +} + +function hide(): void { + if (!$("#videoAdPopupWrapper").hasClass("hidden")) { + $("#videoAdPopupWrapper") + .stop(true, true) + .css("opacity", 1) + .animate( + { + opacity: 0, + }, + 100, + () => { + $("#videoAdPopupWrapper").addClass("hidden"); + } + ); + } +} + +$(".pageTest #watchVideoAdButton").on("click", () => { + show(); +}); + +$("#videoAdPopup .button").on("click", (e) => { + hide(); +}); diff --git a/frontend/src/ts/test/focus.ts b/frontend/src/ts/test/focus.ts index 032e6f66f..a44324482 100644 --- a/frontend/src/ts/test/focus.ts +++ b/frontend/src/ts/test/focus.ts @@ -23,6 +23,7 @@ export function set(foc: boolean, withCursor = false): void { $("#middle").removeClass("focus"); $("#bannerCenter").removeClass("focus"); $("#capsWarning").removeClass("focus"); + $("#app").removeClass("focus"); } } diff --git a/frontend/src/ts/test/result.ts b/frontend/src/ts/test/result.ts index 6594f6822..066309442 100644 --- a/frontend/src/ts/test/result.ts +++ b/frontend/src/ts/test/result.ts @@ -14,6 +14,7 @@ import * as TestInput from "./test-input"; import * as Notifications from "../elements/notifications"; import * as Loader from "../elements/loader"; import QuotesController from "../controllers/quotes-controller"; +import * as AdController from "../controllers/ad-controller"; import { Chart } from "chart.js"; import { Auth } from "../firebase"; @@ -710,6 +711,7 @@ export async function update( $("#result"), 250, async () => { + AdController.renderResult(); TestUI.setResultCalculating(false); $("#words").empty(); ChartController.result.resize(); diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index ea3a104ad..41baf942c 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -53,6 +53,7 @@ import * as Monkey from "./monkey"; import objectHash from "object-hash"; import * as AnalyticsController from "../controllers/analytics-controller"; import { Auth } from "../firebase"; +import * as AdController from "../controllers/ad-controller"; let failReason = ""; @@ -483,6 +484,7 @@ export function restart( $("#monkey").stop(true, true).css({ animationDuration: "0s" }); $("#typingTest").css("opacity", 0).removeClass("hidden"); $("#wordsInput").val(" "); + AdController.destroyResult(); let shouldQuoteRepeat = false; if ( Config.mode === "quote" && diff --git a/frontend/src/ts/types/types.d.ts b/frontend/src/ts/types/types.d.ts index 5237e2966..b2ea076db 100644 --- a/frontend/src/ts/types/types.d.ts +++ b/frontend/src/ts/types/types.d.ts @@ -102,7 +102,7 @@ declare namespace MonkeyTypes { type HighlightMode = "off" | "letter" | "word"; - type EnableAds = "off" | "on" | "max"; + type Ads = "off" | "result" | "on" | "sellout"; type MinimumAccuracy = "off" | "custom"; @@ -363,7 +363,7 @@ declare namespace MonkeyTypes { minWpmCustomSpeed: number; highlightMode: HighlightMode; alwaysShowCPM: boolean; - enableAds: EnableAds; + ads: Ads; hideExtraLetters: boolean; strictSpace: boolean; minAcc: MinimumAccuracy; diff --git a/frontend/static/html/pages/about.html b/frontend/static/html/pages/about.html index 5e1ea0bc4..63d96f641 100644 --- a/frontend/static/html/pages/about.html +++ b/frontend/static/html/pages/about.html @@ -71,7 +71,14 @@ mapped onto a scale from 0 to 100.

- + +

results screen

@@ -217,7 +224,14 @@ themes and more

- + +

supporters

diff --git a/frontend/static/html/pages/account.html b/frontend/static/html/pages/account.html index 3b19ee42f..5864b2b12 100644 --- a/frontend/static/html/pages/account.html +++ b/frontend/static/html/pages/account.html @@ -280,7 +280,14 @@ - +
+
+
+
+
+
+
+
+ +
diff --git a/frontend/static/html/pages/settings.html b/frontend/static/html/pages/settings.html index cb29f572d..5baa33816 100644 --- a/frontend/static/html/pages/settings.html +++ b/frontend/static/html/pages/settings.html @@ -27,7 +27,16 @@ danger zone - + + + + - + +
sound @@ -1605,7 +1621,14 @@
- + +
theme @@ -2308,24 +2331,27 @@
-
-

enable ads

+
+

ads

- If you wish to support me without directly donating you can enable ads - that will be visible at the bottom of the screen. Sellout mode also - shows ads on both sides of the screen. + You can disable or enable ads at any time. "Result" will show one ad on + the result page, "on" will add floating vertical banners, and "sellout" + will add multiple ads on every page.

(changes will take effect after a refresh).
-
+
off
-
+
+ result +
+
on
-
+
sellout
@@ -2361,9 +2387,7 @@ change your preferences here.
-
- open -
+
open
+
+ +
+
+ +
diff --git a/frontend/static/html/popups.html b/frontend/static/html/popups.html index 3edc45d23..5855f0e65 100644 --- a/frontend/static/html/popups.html +++ b/frontend/static/html/popups.html @@ -64,14 +64,19 @@
- + +