portrait-only: drop landscape rotate prompt + lock to portrait
- Remove RotatePrompt (the "rotate to landscape" overlay) — the app is portrait now, so it only blocked the UI. - page.tsx: best-effort orientation lock switched landscape → portrait. - Add Playwright-based store-screenshot + icon scripts (scripts/shots.js, game.js, icon.js); generated images are gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
// Capture several frames of an actual vs-computer game so we can pick the best
|
||||
// "gameplay" shot (hand fanned at the bottom, trump chosen, a trick in play).
|
||||
const { chromium } = require("playwright");
|
||||
const path = require("path");
|
||||
const OUT = path.join(__dirname, "shots");
|
||||
const URL = process.env.SHOT_URL || "http://localhost:3025/";
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch({ channel: "chrome" });
|
||||
const ctx = await browser.newContext({
|
||||
viewport: { width: 430, height: 932 },
|
||||
deviceScaleFactor: 2,
|
||||
locale: "fa-IR",
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
});
|
||||
const page = await ctx.newPage();
|
||||
await page.goto(URL, { waitUntil: "networkidle" }).catch(() => {});
|
||||
await page.waitForTimeout(2500);
|
||||
|
||||
await page.getByText("بازی با کامپیوتر", { exact: false }).first().click();
|
||||
// Capture a frame every few seconds through deal → hakem → trump → play.
|
||||
const stamps = [6, 10, 14, 18, 24, 30];
|
||||
let prev = 0;
|
||||
for (const s of stamps) {
|
||||
await page.waitForTimeout((s - prev) * 1000);
|
||||
prev = s;
|
||||
await page.screenshot({ path: path.join(OUT, `game-${String(s).padStart(2, "0")}s.png`) });
|
||||
// If it's our turn to choose trump, pick the first suit so play proceeds.
|
||||
try {
|
||||
const trump = page.getByText("حکم را انتخاب", { exact: false });
|
||||
if (await trump.count()) {
|
||||
const suit = page.locator("button").filter({ hasText: /♠|♥|♦|♣/ }).first();
|
||||
if (await suit.count()) await suit.click({ timeout: 1500 }).catch(() => {});
|
||||
}
|
||||
} catch {}
|
||||
console.log("frame", s + "s");
|
||||
}
|
||||
await browser.close();
|
||||
console.log("DONE");
|
||||
})().catch((e) => { console.error("FATAL", e); process.exit(1); });
|
||||
@@ -0,0 +1,24 @@
|
||||
// Render public/icon.svg to a 512x512 store PNG (full square — stores apply
|
||||
// their own corner mask). Uses Chrome for correct Persian text shaping.
|
||||
const { chromium } = require("playwright");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const OUT = path.join(__dirname, "shots");
|
||||
fs.mkdirSync(OUT, { recursive: true });
|
||||
|
||||
let svg = fs.readFileSync(path.join(__dirname, "..", "public", "icon.svg"), "utf8");
|
||||
// Full-bleed square (remove the rounded corners so there's no transparency).
|
||||
const square = svg.replace('rx="112"', 'rx="0"').replace("<svg ", '<svg width="512" height="512" ');
|
||||
const html = `<!doctype html><html><head><meta charset="utf-8"></head><body style="margin:0;padding:0">${square}</body></html>`;
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch({ channel: "chrome" });
|
||||
const ctx = await browser.newContext({ viewport: { width: 512, height: 512 }, deviceScaleFactor: 1 });
|
||||
const page = await ctx.newPage();
|
||||
await page.setContent(html, { waitUntil: "networkidle" });
|
||||
await page.waitForTimeout(600);
|
||||
await page.screenshot({ path: path.join(OUT, "icon-512.png"), clip: { x: 0, y: 0, width: 512, height: 512 } });
|
||||
await browser.close();
|
||||
console.log("icon-512 done");
|
||||
})().catch((e) => { console.error("FATAL", e); process.exit(1); });
|
||||
@@ -0,0 +1,69 @@
|
||||
// Capture portrait store screenshots from the running dev server (localhost:3025)
|
||||
// using the system Chrome. Output -> scripts/shots/*.png
|
||||
const { chromium } = require("playwright");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const OUT = path.join(__dirname, "shots");
|
||||
fs.mkdirSync(OUT, { recursive: true });
|
||||
const URL = process.env.SHOT_URL || "http://localhost:3025/";
|
||||
|
||||
const shot = async (page, name) => {
|
||||
await page.screenshot({ path: path.join(OUT, name + ".png") });
|
||||
console.log("saved", name);
|
||||
};
|
||||
const tap = async (page, text) => {
|
||||
const el = page.getByText(text, { exact: false }).first();
|
||||
await el.click({ timeout: 6000 });
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch({ channel: "chrome" });
|
||||
const ctx = await browser.newContext({
|
||||
viewport: { width: 430, height: 932 },
|
||||
deviceScaleFactor: 2,
|
||||
locale: "fa-IR",
|
||||
isMobile: true,
|
||||
hasTouch: true,
|
||||
});
|
||||
const page = await ctx.newPage();
|
||||
await page.goto(URL, { waitUntil: "networkidle" }).catch(() => {});
|
||||
await page.waitForTimeout(3000);
|
||||
await shot(page, "01-home");
|
||||
|
||||
// nav-rail screens reachable from home
|
||||
for (const [label, name] of [
|
||||
["جدول امتیازات", "02-leaderboard"],
|
||||
["دستاوردها", "03-achievements"],
|
||||
["فروشگاه", "04-shop"],
|
||||
["پروفایل", "05-profile"],
|
||||
]) {
|
||||
try {
|
||||
await tap(page, label);
|
||||
await page.waitForTimeout(2200);
|
||||
await shot(page, name);
|
||||
// back to home for the next nav tap
|
||||
await page.goto(URL, { waitUntil: "networkidle" }).catch(() => {});
|
||||
await page.waitForTimeout(1500);
|
||||
} catch (e) {
|
||||
console.log("skip", name, String(e).split("\n")[0]);
|
||||
await page.goto(URL, { waitUntil: "networkidle" }).catch(() => {});
|
||||
await page.waitForTimeout(1500);
|
||||
}
|
||||
}
|
||||
|
||||
// vs-computer game (cards on the table)
|
||||
try {
|
||||
await tap(page, "بازی با کامپیوتر");
|
||||
await page.waitForTimeout(5000);
|
||||
await shot(page, "06-game");
|
||||
} catch (e) {
|
||||
console.log("skip game", String(e).split("\n")[0]);
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log("DONE");
|
||||
})().catch((e) => {
|
||||
console.error("FATAL", e);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user