This commit is contained in:
commit
76dbed117f
9 changed files with 108 additions and 24 deletions
14
PLAN.md
14
PLAN.md
|
|
@ -284,3 +284,17 @@ Abgabe: **9. Dezember 2026, 03:00 MEZ**. Eingereicht wird in „Best Daily Game
|
||||||
Aufnahmen werden vorher nach VP9/WebM umgewandelt.
|
Aufnahmen werden vorher nach VP9/WebM umgewandelt.
|
||||||
- Reddit selbst (Feed, Kommentar im Thread, Flair) nimmt der Besitzer mit seinem Konto auf (Reddit blockt
|
- Reddit selbst (Feed, Kommentar im Thread, Flair) nimmt der Besitzer mit seinem Konto auf (Reddit blockt
|
||||||
Automatisierung); optional als `dist/trailer/input/feed.*` / `comment.*`.
|
Automatisierung); optional als `dist/trailer/input/feed.*` / `comment.*`.
|
||||||
|
|
||||||
|
### 2026-11-13 – Realm im Vollbild (Bug vom Besitzer)
|
||||||
|
|
||||||
|
- **Bug:** Am Handy öffnete „🎨 Realm“ das Fenster im Inline-Post (512 px hoch). Die Liste ist höher, „Done“ lag
|
||||||
|
außerhalb, und scrollen darf ein Inline-Post nicht (Devvit-Regel „Scrolling within inline webviews is prohibited“,
|
||||||
|
Scroll-Falle im Feed) → man saß fest.
|
||||||
|
- **Lösung:** eigener Einstiegspunkt `realm` (`public/realm.html`, `src/client/realm-page.ts`), geöffnet mit
|
||||||
|
`requestExpandedMode(ev, 'realm', {title: 'Your realm'})`; „Done“ ruft `exitExpandedMode`. Der Knopf klebt unten
|
||||||
|
(`position: sticky`), damit er auch bei langer Liste sichtbar bleibt. Der Startbildschirm lädt beim `focus`-Ereignis
|
||||||
|
(Rückkehr aus dem Vollbild, laut Doku der Ersatz für `addWebViewModeListener`) Tag und Aussehen neu – damit zeigt er
|
||||||
|
nach dem Spielen auch gleich das eigene Ergebnis.
|
||||||
|
- Credits-Fenster im Post geprüft: passt auch bei 320 px Breite (Knopf endet bei 413 von 512 px).
|
||||||
|
- Pixelify-Ligatur „fi“ (sieht aus wie „A“) jetzt für die ganze App aus (`font-variant-ligatures: none`).
|
||||||
|
- **Fallstrick:** `devvit.json` geändert → laufenden Playtest stoppen und neu starten.
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@
|
||||||
},
|
},
|
||||||
"game": {
|
"game": {
|
||||||
"entry": "game.html"
|
"entry": "game.html"
|
||||||
|
},
|
||||||
|
"realm": {
|
||||||
|
"entry": "realm.html"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run build:client -- --metafile=dist/client.meta.json --minify && npm run build:server -- --metafile=dist/server.meta.json --minify",
|
"build": "npm run build:client -- --metafile=dist/client.meta.json --minify && npm run build:server -- --metafile=dist/server.meta.json --minify",
|
||||||
"build:client": "esbuild --bundle --log-level=warning --sourcemap=linked --target=es2023 --format=esm --outdir=public --platform=browser --define:import.meta.env.MODE='\"reddit\"' --define:import.meta.env.BASE_URL='\"/\"' --define:__API_ORIGIN__='\"\"' --loader:.woff2=file --loader:.woff=file --asset-names=fonts/[name]-[hash] src/client/splash.ts src/client/game.ts",
|
"build:client": "esbuild --bundle --log-level=warning --sourcemap=linked --target=es2023 --format=esm --outdir=public --platform=browser --define:import.meta.env.MODE='\"reddit\"' --define:import.meta.env.BASE_URL='\"/\"' --define:__API_ORIGIN__='\"\"' --loader:.woff2=file --loader:.woff=file --asset-names=fonts/[name]-[hash] src/client/splash.ts src/client/game.ts src/client/realm-page.ts",
|
||||||
"build:server": "esbuild --bundle --log-level=warning --sourcemap=linked --target=es2023 --format=cjs --outdir=dist/server --platform=node src/server/index.ts",
|
"build:server": "esbuild --bundle --log-level=warning --sourcemap=linked --target=es2023 --format=cjs --outdir=dist/server --platform=node src/server/index.ts",
|
||||||
"clean": "rm -rf dist/ public/*.js* public/*.css* public/fonts/",
|
"clean": "rm -rf dist/ public/*.js* public/*.css* public/fonts/",
|
||||||
"format": "npm run lint -- --fix",
|
"format": "npm run lint -- --fix",
|
||||||
|
|
|
||||||
14
public/realm.html
Normal file
14
public/realm.html
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Ninelands</title>
|
||||||
|
<link rel="stylesheet" href="realm-page.css">
|
||||||
|
<link rel="modulepreload" href="realm-page.js">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script src="realm-page.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -349,17 +349,24 @@ async function scenes(page, o) {
|
||||||
'Streaks and stars unlock boards, peoples and banners.',
|
'Streaks and stars unlock boards, peoples and banners.',
|
||||||
)
|
)
|
||||||
await wait(900)
|
await wait(900)
|
||||||
const s2 = frameOf('splash.html')
|
// Realm öffnet im Vollbild (requestExpandedMode gibt es hier nicht → nur antippen, Bühne wechselt)
|
||||||
await tap(s2.locator('.realm-btn'), 300)
|
await tap(frameOf('splash.html').locator('.realm-btn'), 300, false)
|
||||||
await wait(700)
|
await wait(300)
|
||||||
await tap(s2.locator('.realm-item', {hasText: 'Winter'}).first(), 400)
|
await stage('finger', null)
|
||||||
|
await stage('show', 'game', '/realm.html')
|
||||||
|
const r = frameOf('realm.html')
|
||||||
|
await r.waitForSelector('.realm-item')
|
||||||
|
await wait(600)
|
||||||
|
await tap(r.locator('.realm-item', {hasText: 'Winter'}).first(), 400)
|
||||||
await wait(900)
|
await wait(900)
|
||||||
await stage('finger', null)
|
await stage('finger', null)
|
||||||
await o.snap('05-realm')
|
await o.snap('05-realm')
|
||||||
await wait(800)
|
await wait(800)
|
||||||
await tap(s2.locator('.overlay button.primary', {hasText: 'Done'}), 300)
|
await tap(r.locator('.overlay button.primary', {hasText: 'Done'}), 300, false)
|
||||||
|
await wait(300)
|
||||||
await stage('finger', null)
|
await stage('finger', null)
|
||||||
await wait(400)
|
await stage('show', 'post', '/splash.html')
|
||||||
|
await wait(700)
|
||||||
|
|
||||||
await stage(
|
await stage(
|
||||||
'caption',
|
'caption',
|
||||||
|
|
|
||||||
35
src/client/realm-page.ts
Normal file
35
src/client/realm-page.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
// „🎨 Realm“ im Vollbild (Einstiegspunkt „realm“): Aussehen wählen, „Done“ führt zurück in den Post.
|
||||||
|
import './style.css'
|
||||||
|
import {exitExpandedMode} from '@devvit/web/client'
|
||||||
|
import {dailyMap} from '../shared/daily.ts'
|
||||||
|
import {fetchDay} from './api.ts'
|
||||||
|
import {byId, h} from './dom.ts'
|
||||||
|
import {applyLook, openRealm} from './realm.ts'
|
||||||
|
|
||||||
|
const app = byId<HTMLDivElement>('app')
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
app.replaceChildren(h('div.loading', 'Loading…'))
|
||||||
|
try {
|
||||||
|
const day = await fetchDay()
|
||||||
|
app.replaceChildren()
|
||||||
|
applyLook(day.look)
|
||||||
|
openRealm({
|
||||||
|
look: day.look,
|
||||||
|
progress: {
|
||||||
|
bestStreak: day.stats?.bestStreak ?? 0,
|
||||||
|
totalStars: day.stats?.totalStars ?? 0,
|
||||||
|
},
|
||||||
|
day: dailyMap(new Date()).day,
|
||||||
|
loggedIn: day.loggedIn,
|
||||||
|
onChange: look => applyLook(look),
|
||||||
|
onClose: ev => exitExpandedMode(ev),
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
app.replaceChildren(
|
||||||
|
h('div.error', `Could not load your realm. ${(err as Error).message}`),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
|
@ -75,6 +75,8 @@ export function openRealm(opts: {
|
||||||
day: string
|
day: string
|
||||||
loggedIn: boolean
|
loggedIn: boolean
|
||||||
onChange: (look: Look) => void
|
onChange: (look: Look) => void
|
||||||
|
/** Statt nur das Fenster zu schließen (Vollbild-Seite: zurück in den Post) */
|
||||||
|
onClose?: (ev: MouseEvent) => void
|
||||||
}): void {
|
}): void {
|
||||||
let look = opts.look
|
let look = opts.look
|
||||||
const body = h('div.realm-rows')
|
const body = h('div.realm-rows')
|
||||||
|
|
@ -94,7 +96,9 @@ export function openRealm(opts: {
|
||||||
h('div.row.end', close),
|
h('div.row.end', close),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
close.addEventListener('click', () => overlay.remove())
|
close.addEventListener('click', ev =>
|
||||||
|
opts.onClose ? opts.onClose(ev) : overlay.remove(),
|
||||||
|
)
|
||||||
|
|
||||||
const row = <T extends string>(
|
const row = <T extends string>(
|
||||||
title: string,
|
title: string,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {dailyBoard, dailyMap, dayLabel} from '../shared/daily.ts'
|
||||||
import {fetchDay} from './api.ts'
|
import {fetchDay} from './api.ts'
|
||||||
import {byId, h} from './dom.ts'
|
import {byId, h} from './dom.ts'
|
||||||
import {appReady} from './journeys.ts'
|
import {appReady} from './journeys.ts'
|
||||||
import {applyLook, openRealm} from './realm.ts'
|
import {applyLook} from './realm.ts'
|
||||||
import {leaderTable} from './result.ts'
|
import {leaderTable} from './result.ts'
|
||||||
import {lawName, starsLine} from './texts.ts'
|
import {lawName, starsLine} from './texts.ts'
|
||||||
|
|
||||||
|
|
@ -28,6 +28,12 @@ async function main(): Promise<void> {
|
||||||
}
|
}
|
||||||
render(day)
|
render(day)
|
||||||
appReady()
|
appReady()
|
||||||
|
// Zurück aus dem Vollbild (Spiel oder Realm): Ergebnis und Aussehen neu holen
|
||||||
|
addEventListener('focus', () => {
|
||||||
|
fetchDay()
|
||||||
|
.then(render)
|
||||||
|
.catch(() => {})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function render(day: GetDayRsp): void {
|
function render(day: GetDayRsp): void {
|
||||||
|
|
@ -38,21 +44,10 @@ function render(day: GetDayRsp): void {
|
||||||
|
|
||||||
const realm = h('button.icon.realm-btn', '🎨 Realm')
|
const realm = h('button.icon.realm-btn', '🎨 Realm')
|
||||||
realm.title = 'Customise your realm'
|
realm.title = 'Customise your realm'
|
||||||
realm.addEventListener('click', () =>
|
// Im Vollbild: der Inline-Post ist nur 512 px hoch und darf nicht scrollen (Devvit-Regel) – sonst wäre
|
||||||
openRealm({
|
// „Done“ am Handy unerreichbar
|
||||||
look: day.look,
|
realm.addEventListener('click', ev =>
|
||||||
progress: {
|
requestExpandedMode(ev, 'realm', {title: 'Your realm'}),
|
||||||
bestStreak: day.stats?.bestStreak ?? 0,
|
|
||||||
totalStars: day.stats?.totalStars ?? 0,
|
|
||||||
},
|
|
||||||
day: dailyMap(new Date()).day,
|
|
||||||
loggedIn: day.loggedIn,
|
|
||||||
onChange: look => {
|
|
||||||
day.look = look
|
|
||||||
applyLook(look)
|
|
||||||
renderMiniBoard(mini, dailyBoard(map))
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const play = h('button.primary', day.mine ? 'Play again' : 'Play')
|
const play = h('button.primary', day.mine ? 'Play again' : 'Play')
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ body {
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--px-grass-dark);
|
background-color: var(--px-grass-dark);
|
||||||
|
/* Pixelify verbindet „fi“ sonst zu einem Zeichen, das wie „A“ aussieht */
|
||||||
|
font-variant-ligatures: none;
|
||||||
/* feines Schachbrett wie Grasnarbe */
|
/* feines Schachbrett wie Grasnarbe */
|
||||||
background-image: conic-gradient(
|
background-image: conic-gradient(
|
||||||
rgba(0, 0, 0, 0.08) 25%,
|
rgba(0, 0, 0, 0.08) 25%,
|
||||||
|
|
@ -219,6 +221,16 @@ button.icon {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- Realm-Auswahl ---------- */
|
/* ---------- Realm-Auswahl ---------- */
|
||||||
|
/* „Done“ bleibt unten sichtbar, auch wenn die Liste scrollt (Vollbild am Handy) */
|
||||||
|
.realm > .row.end {
|
||||||
|
position: sticky;
|
||||||
|
bottom: -1rem;
|
||||||
|
margin: 0 -1rem -1rem;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
background: var(--px-wood);
|
||||||
|
border-top: 2px solid var(--px-ink);
|
||||||
|
}
|
||||||
|
|
||||||
.realm h3 {
|
.realm h3 {
|
||||||
margin: 0 0 0.25rem;
|
margin: 0 0 0.25rem;
|
||||||
font-family: var(--font-pixel);
|
font-family: var(--font-pixel);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue