mirror of
https://github.com/Such-Software/bauhaus-echo-web.git
synced 2026-10-17 05:51:24 +02:00
- app-config.js: public config placeholder (all null/false -> INERT). Operations populates OIDC client + shop tenant + checkout URL at deploy; no secrets. - checkout.js: Authorization Code + S256 PKCE (public client, no secret), state CSRF guard, token in sessionStorage, code/state scrubbed from URL. Resolves premium via the ledger's per-user /me/entitlements (user's own OIDC token, never the shared read token) and sets window.SUCH_APP.premium for WebBillingManager. Redemption also resolves on page reload / next login (crypto is webhook-driven). - index.html: load config+checkout in <head>; CTA calls SUCH_APP_startCheckout, else falls through to the store links (fail-closed). Store/itch buttons unchanged.
153 lines
5.3 KiB
HTML
153 lines
5.3 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Bauhaus Echo</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<meta id="gameViewport" name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" type="image/png" href="favicon.png">
|
|
<link href="styles.css" rel="stylesheet" type="text/css">
|
|
|
|
<!-- Google AdSense — auto ads enabled at account level -->
|
|
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2501747033825166"
|
|
crossorigin="anonymous"></script>
|
|
|
|
<!-- Fail-closed web-app → checkout wiring. Inert until Operations populates
|
|
app-config.js (OIDC client + shop tenant); no secrets. -->
|
|
<script src="app-config.js"></script>
|
|
<script src="checkout.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- ================================================================= -->
|
|
<!-- NAG OVERLAY — shown before first game and between every game -->
|
|
<!-- ================================================================= -->
|
|
<div id="nag-overlay">
|
|
<div id="nag-box">
|
|
<div id="nag-header">
|
|
<h1 id="nag-title">BAUHAUS ECHO</h1>
|
|
<p id="nag-tagline">A visual memory puzzle</p>
|
|
</div>
|
|
|
|
<div id="nag-pitch">
|
|
<p><strong>Love it? Get the full Bauhaus Echo.</strong></p>
|
|
<p>Every tile pack, the new Puzzle mode & screensavers, and no ads.</p>
|
|
</div>
|
|
|
|
<div id="nag-store-links">
|
|
<!-- PRIMARY: real checkout when configured; else falls through to the apex
|
|
marketing site. checkout.js returns true when it starts OIDC login (we
|
|
then preventDefault); false → the href proceeds (fail-closed). -->
|
|
<a href="https://bauhausecho.com"
|
|
target="_blank" rel="noopener noreferrer"
|
|
class="nag-btn nag-btn-primary"
|
|
onclick="return !(window.SUCH_APP_startCheckout && window.SUCH_APP_startCheckout())">
|
|
Get the Full Game ▸
|
|
</a>
|
|
|
|
<!-- SECONDARY: the native stores -->
|
|
<div id="nag-mobile-row">
|
|
<a href="https://apps.apple.com/us/app/bauhaus-echo/id6759010657"
|
|
target="_blank" rel="noopener noreferrer"
|
|
class="nag-btn nag-btn-store">
|
|
App Store
|
|
</a>
|
|
<a href="https://play.google.com/store/apps/details?id=com.suchsoftware.bauhausecho"
|
|
target="_blank" rel="noopener noreferrer"
|
|
class="nag-btn nag-btn-store">
|
|
Google Play
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Tertiary: the ad-free desktop build -->
|
|
<a href="https://suchsoftware.itch.io/bauhaus-echo"
|
|
target="_blank" rel="noopener noreferrer"
|
|
id="nag-itch-link">or the ad-free desktop build on itch.io</a>
|
|
</div>
|
|
|
|
<div id="nag-divider"></div>
|
|
|
|
<!-- AdSense display ad — replace data-ad-slot with your unit ID -->
|
|
<div id="nag-ad-container">
|
|
<ins class="adsbygoogle"
|
|
style="display:block"
|
|
data-ad-client="ca-pub-2501747033825166"
|
|
data-ad-slot="3097663248"
|
|
data-ad-format="auto"
|
|
data-full-width-responsive="true"></ins>
|
|
</div>
|
|
|
|
<button id="nag-continue" onclick="dismissNagOverlay()">
|
|
Continue to Web Version ▸
|
|
</button>
|
|
|
|
<p id="nag-fine-print">Free with ads between games</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Game canvas container -->
|
|
<div align="center" id="embed-html"></div>
|
|
|
|
<script>
|
|
// ================================================================
|
|
// Nag overlay state machine
|
|
// ================================================================
|
|
(function() {
|
|
var overlay = document.getElementById('nag-overlay');
|
|
var embed = document.getElementById('embed-html');
|
|
var gwtLoaded = false;
|
|
|
|
// Request the first ad for the initial overlay (defer until layout is done)
|
|
setTimeout(function() {
|
|
try { (adsbygoogle = window.adsbygoogle || []).push({}); } catch(e) { console.warn('AdSense init error:', e); }
|
|
}, 500);
|
|
|
|
// Called when user clicks "Continue to Web Version"
|
|
// Also called from GwtAdManager via JSNI after between-game nag
|
|
window.dismissNagOverlay = function() {
|
|
overlay.style.display = 'none';
|
|
|
|
// If a rewarded-ad session was pending, notify GWT
|
|
if (window.__gwtRewardCallback) {
|
|
try { window.__gwtRewardCallback(); } catch(e) {}
|
|
}
|
|
|
|
if (!gwtLoaded) {
|
|
// First dismiss: inject GWT script to start the game
|
|
var s = document.createElement('script');
|
|
s.type = 'text/javascript';
|
|
s.src = 'html/html.nocache.js';
|
|
document.body.appendChild(s);
|
|
gwtLoaded = true;
|
|
|
|
// Attach input handlers once GWT creates the canvas
|
|
s.onload = function() {
|
|
setTimeout(function() {
|
|
embed.addEventListener('mousedown', blockDefault, false);
|
|
embed.addEventListener('mouseup', blockDefault, false);
|
|
}, 500);
|
|
};
|
|
}
|
|
};
|
|
|
|
// Called from GwtAdManager.showInterstitialAd() via JSNI
|
|
// Shows the nag overlay on top of the running game
|
|
window.showNagOverlay = function() {
|
|
overlay.style.display = 'flex';
|
|
// Request a fresh ad each time the overlay appears
|
|
try { (adsbygoogle = window.adsbygoogle || []).push({}); } catch(e) {}
|
|
};
|
|
|
|
// Block right-click and default mouse behaviour on the canvas
|
|
function blockDefault(evt) {
|
|
evt.preventDefault();
|
|
evt.stopPropagation();
|
|
window.focus();
|
|
}
|
|
document.addEventListener('contextmenu', function(e) { e.preventDefault(); });
|
|
})();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|