Skip to content

Commit bef234a

Browse files
committed
better loading, gtag, logging, added version tag in /version.txt
1 parent f4c3eb6 commit bef234a

12 files changed

Lines changed: 200 additions & 66 deletions

File tree

echodate.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(new Date().toISOString())

src/app.html

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,6 @@
22
<html lang="en">
33

44
<head>
5-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DJDL65P9Y4"></script>
6-
<script>
7-
window.dataLayer = window.dataLayer || [];
8-
function gtag() {
9-
dataLayer.push(arguments);
10-
}
11-
gtag("js", new Date());
12-
13-
gtag("config", "G-DJDL65P9Y4");
14-
window.gtag = gtag;
15-
</script>
165
<meta charset="utf-8" />
176
<link rel="icon" href="%sveltekit.assets%/ccported_logo.webp" />
187
<meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -28,9 +17,46 @@
2817

2918

3019
<script>
20+
console.log('[APP][head] Loaded app');
3121
if ("serviceWorker" in navigator) {
22+
console.log(`[APP][head][check-sw] Service worker supported, registering...`);
3223
navigator.serviceWorker.register("%sveltekit.assets%/sw.js");
24+
25+
navigator.serviceWorker.ready.then((registration) => {
26+
if (registration.active) {
27+
registration.active.postMessage("Test message sent immediately after creation");
28+
}
29+
30+
const version = localStorage.getItem("ccported-version");
31+
fetch("%sveltekit.assets%/version.txt").then(async (res) => {
32+
if (!res.ok) {
33+
console.log(`[APP][head][check-version] Failed to fetch version.txt: ${res.status}`);
34+
return;
35+
}
36+
const text = (await res.text()).trim();
37+
console.log(`[APP][head][check-version] Fetched version.txt content: "${text}"`);
38+
const newVersion = new Date(text);
39+
const oldVersion = version ? new Date(version) : null;
40+
console.log(`[APP][head][check-version] Fetched version: ${newVersion}, old version: ${oldVersion}`);
41+
if (!oldVersion || newVersion > oldVersion) {
42+
localStorage.setItem("ccported-version", newVersion.toISOString());
43+
console.log(`[APP][head][check-version] New version available update sw, clearing cache -> reload...`);
44+
registration.update();
45+
registration.active?.postMessage({ action: "CLEAR_CACHE" });
46+
}
47+
});
48+
49+
navigator.serviceWorker.addEventListener("message", (event) => {
50+
if (event.data && event.data.type === "CACHE_CLEARED") {
51+
console.log(`[APP][head][check-version][sw-message] ${event.data.status}`);
52+
}
53+
});
54+
});
55+
} else {
56+
console.log(`[APP][head][check-sw] Service worker not supported`);
3357
}
58+
59+
console.log("[APP][head] Test message");
3460
</script>
3561
</head>
3662

src/lib/components/CardGrid.svelte

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44
detectAdBlockEnabled,
55
openGame,
66
} from "$lib/helpers.js";
7-
import { SessionState, State } from "$lib/state.js";
7+
import { initializeTooling, SessionState, State } from "$lib/state.js";
88
import type { Game } from "$lib/types/game.js";
99
import { onMount } from "svelte";
1010
import GameCard from "./GameCard.svelte";
1111
import Ad from "./Ad.svelte";
1212
import { findAHosts } from "$lib/types/servers.js";
1313
import { browser } from "$app/environment";
14+
import { loadGames } from "$lib/loadCards.js";
1415
15-
const props: { games: Game[] } = $props();
1616
let searchIsOpen = $state(false);
17-
const { games } = props;
18-
17+
let games = $state<Game[]>([]);
1918
let adsEnabled = $state(false);
2019
let adSlots = $state<{ sidebar: string; grid: string } | null>(null);
2120
@@ -82,9 +81,8 @@
8281
});
8382
}
8483
console.log(
85-
`Sorted games by ${sortType}:`,
86-
sorted.length
87-
)
84+
`[R][CardGrid][getSortedGames] Sorted games by ${sortType}, found ${sorted.length} games.`,
85+
);
8886
return sorted;
8987
}
9088
@@ -179,6 +177,10 @@
179177
const searchRegex = /[a-z0-9]/i;
180178
let adBlock = $state(false);
181179
onMount(async () => {
180+
await initializeTooling();
181+
182+
games = await loadGames();
183+
182184
document.addEventListener("keydown", (e) => {
183185
if (!searchInput) return;
184186
// Ignore keyboard shortcuts, special keys, non a-z0-9, or backspace, enter, delete, etc.
@@ -226,7 +228,7 @@
226228
if (SessionState.ssr) return;
227229
228230
await detectAdBlockEnabled();
229-
console.log("AdBlock Enabled:", SessionState.adBlockEnabled);
231+
console.log("[R][CardGrid][Mount] AdBlock Enabled:", SessionState.adBlockEnabled);
230232
adBlock = SessionState.adBlockEnabled;
231233
adsEnabled = SessionState.adsEnabled;
232234
if (adsEnabled) {
@@ -395,6 +397,11 @@
395397
</button>
396398
</div>
397399
<div class="card-grid {State.homeView}">
400+
{#if games.length === 0}
401+
{#each Array(12) as _, i}
402+
<div class="load-shimmer">&nbsp;</div>
403+
{/each}
404+
{/if}
398405
{#each getSortedGames() as game, i (game.gameID)}
399406
<GameCard
400407
{game}
@@ -411,8 +418,15 @@
411418
{#if !adBlock && !adsEnabled}
412419
{#if (i + 1) % 10 === 0}
413420
<div class="inxxx agrid grid">
414-
<div style="text-align: center; font-size: 0.9rem; color: #555;width:100%;height:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;">
415-
<p>Contact <a href="mailto:ccported@ccported.click">ccported@ccported.click</a> to advertise in this slot</p>
421+
<div
422+
style="text-align: center; font-size: 0.9rem; color: #555;width:100%;height:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;"
423+
>
424+
<p>
425+
Contact <a
426+
href="mailto:ccported@ccported.click"
427+
>ccported@ccported.click</a
428+
> to advertise in this slot
429+
</p>
416430
</div>
417431
</div>
418432
{/if}
@@ -430,6 +444,31 @@
430444
</div>
431445

432446
<style>
447+
.load-shimmer {
448+
width: 90%;
449+
height: 280px;
450+
border-radius: 16px;
451+
border: 1px solid #e0e0e0;
452+
background: linear-gradient(
453+
90deg,
454+
#f0f0f0 0%,
455+
#e0e0e0 50%,
456+
#f0f0f0 100%
457+
);
458+
background-size: 200% 100%;
459+
animation: shimmer 1.5s infinite linear;
460+
margin-bottom: 20px;
461+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
462+
}
463+
464+
@keyframes shimmer {
465+
0% {
466+
background-position: 200% 0;
467+
}
468+
100% {
469+
background-position: -200% 0;
470+
}
471+
}
433472
.container {
434473
width: 100%;
435474
box-sizing: border-box;

src/lib/components/Info.svelte

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,24 @@
77
let stateFulState = $state(State);
88
let stateFulSessionState = $state(SessionState);
99
let plays = $state(SessionState.plays);
10+
let version = $state("Fetching...")
1011
onMount(async () => {
1112
await waitForTooling();
1213
stateFulState = State;
1314
stateFulSessionState = SessionState;
1415
plays = SessionState.plays;
16+
if (browser) {
17+
try {
18+
const res = await fetch("/version.txt", { method: "GET" });
19+
if (res.ok) {
20+
version = (await res.text()).trim();
21+
} else {
22+
version = "Error fetching version";
23+
}
24+
} catch (e) {
25+
version = "Error fetching version";
26+
}
27+
}
1528
})
1629
</script>
1730

@@ -86,7 +99,7 @@
8699
<br />
87100
Games Loaded: {stateFulState.games.length} ({stateFulState.pinnedGames
88101
.length} pinned) - rendered {stateFulState.homeView}<br />
89-
Version: {stateFulState.version}<br />
102+
Version: {version}<br />
90103
Logged In: {stateFulSessionState.loggedIn}<br />
91104
SSR: {stateFulSessionState.ssr}<br />
92105
<table

src/lib/state.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export const SessionState = {
2525

2626

2727
type StateType = {
28-
version: string;
2928
servers: typeof Servers;
3029
aHosts: typeof AHosts;
3130
currentServer: Server;
@@ -41,7 +40,7 @@ function saveState() {
4140
if (SessionState.ssr) return;
4241

4342
// Things we don't want to save
44-
const { servers, aHosts, version, games, isAHost, ...serializable } = State;
43+
const { servers, aHosts, games, isAHost, ...serializable } = State;
4544
localStorage.setItem("ccported_state", JSON.stringify(serializable));
4645
}
4746

@@ -58,7 +57,6 @@ function createState(initial: StateType): StateType {
5857
}
5958

6059
export const State = createState({
61-
version: "2.0.0.9.11.25",
6260
servers: Servers,
6361
aHosts: AHosts,
6462
currentServer: Servers[0],
@@ -71,9 +69,15 @@ export const State = createState({
7169

7270

7371
export let toolingInitialized = false;
74-
72+
export let initializingTooling = false;
7573
export async function initializeTooling() {
7674
if (toolingInitialized) return;
75+
if (initializingTooling) {
76+
// Wait for existing initialization to complete
77+
await waitForTooling();
78+
return;
79+
}
80+
initializingTooling = true;
7781
const server = await findServer();
7882
if (!server) {
7983
console.error("No available servers found.");
@@ -106,23 +110,23 @@ export function waitForTooling(): Promise<void> {
106110
clearInterval(checkInterval);
107111
resolve();
108112
}
109-
}, 100);
113+
}, 50);
110114
});
111115
}
112116

113117
export async function findServer(): Promise<Server | null> {
114-
console.log("Searching for servers")
118+
console.log("[STATE][findServer] Searching for servers")
115119
const servers = await findServers();
116120
State.servers = servers;
117-
console.log(`Discovered ${servers.length} servers.`);
121+
console.log(`[STATE][findServer] Discovered ${servers.length} servers.`);
118122
for (let server of State.servers.sort((a, b) => a.priority - b.priority)) {
119-
console.log(`Testing server ${server.name} (${server.hostname}) with priority ${server.priority}`);
123+
console.log(`[STATE][findServer] Testing server ${server.name} (${server.hostname}) with priority ${server.priority}`);
120124
await testServer(server);
121125
}
122126

123127
// Already sorted by priority, so first success is best
124128
const best = SessionState.serverResponses.find(r => r.success)?.server;
125-
console.log("Best server found:", best?.name);
129+
console.log("[STATE][findServer] Best server found:", best?.name);
126130
return best || null;
127131
}
128132

src/lib/types/servers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ export const Servers: Server[] = [{
5656

5757

5858
export const findServers = async (): Promise<Server[]> => {
59-
console.log("Finding servers from servers.txt");
59+
console.log("[SERVERS][findServers] Finding servers from servers.txt");
6060
const url = typeof window !== "undefined" ? `${window.location.origin}/servers.txt` : "https://ccgstatic.com/servers.txt";
61-
console.log(`Fetching servers from ${url}`);
61+
console.log(`[SERVERS][findServers] Fetching servers from ${url}`);
6262
const response = await fetch(url);
63-
console.log(`Response status: ${response.status}`);
63+
console.log(`[SERVERS][findServers] Response status: ${response.status}`);
6464
if (!response.ok) {
6565
return Servers;
6666
}

src/routes/+layout.svelte

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,49 @@
11
<script lang="ts">
2+
import { browser } from "$app/environment";
3+
24
let { children } = $props();
5+
6+
let ga4Codes = {
7+
"ccported.click": "G-ER9VZ5QL8K",
8+
"ccported.github.io": "G-ER9VZ5QL8K",
9+
"localhost": null,
10+
};
11+
let defaultGA4Code = "G-DJDL65P9Y4";
12+
13+
let idToUse = $state(defaultGA4Code);
14+
let useGA4 = $state(true);
15+
if (browser) {
16+
let hostname = window.location.hostname;
17+
console.log("[R][LAYOUT][BASE] Hostname:", hostname);
18+
if (hostname in ga4Codes) {
19+
const code = ga4Codes[hostname as keyof typeof ga4Codes];
20+
if (code) {
21+
idToUse = code;
22+
} else {
23+
useGA4 = false;
24+
}
25+
}
26+
}
327
</script>
428

29+
<svelte:head>
30+
<meta name = "use-ga4" content = {String(useGA4)} />
31+
{#if useGA4}
32+
<script
33+
async
34+
src="https://www.googletagmanager.com/gtag/js?id={idToUse}"
35+
></script>
36+
37+
{@html `
38+
<script>
39+
window.dataLayer = window.dataLayer || [];
40+
function gtag(){dataLayer.push(arguments);}
41+
gtag('js', new Date());
542
43+
gtag('config', '${idToUse}');
44+
</script>
45+
`}
46+
{/if}
47+
</svelte:head>
648

7-
{@render children()}
49+
{@render children()}

src/routes/+page.svelte

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,16 @@
55
import Info from "$lib/components/Info.svelte";
66
import { initializeTooling, SessionState, State } from "$lib/state.js";
77
import { onMount } from "svelte";
8-
import type { PageData } from "./$types.js";
9-
import { browser } from "$app/environment";
10-
import { page } from "$app/state";
118
import { loadGames } from "$lib/loadCards.js";
129
1310
let isAHost = $state(State.isAHost());
1411
let devMode = $state(true);
1512
let adblockEnabled = $state(SessionState.adBlockEnabled);
1613
let adsEnabled = $state(SessionState.adsEnabled);
17-
let sResponses = $state(SessionState.serverResponses);
18-
let games = $state(State.games);
1914
onMount(async () => {
2015
await initializeTooling();
2116
isAHost = State.isAHost();
2217
23-
games = await loadGames();
2418
devMode = SessionState.devMode;
2519
adblockEnabled = SessionState.adBlockEnabled;
2620
adsEnabled = SessionState.adsEnabled;
@@ -39,7 +33,7 @@
3933
<div class="container">
4034
<div class="background"></div>
4135
<Navigation />
42-
<CardGrid {games} />
36+
<CardGrid />
4337
</div>
4438
{:else}
4539
<Locked />

0 commit comments

Comments
 (0)