@mblinkov/whats-missing 20.0.46 → 20.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -1
- package/dist/whats-missing.cjs.js +3 -3
- package/dist/whats-missing.es.js +151 -182
- package/package.json +1 -1
- package/src/Game.tsx +136 -191
package/package.json
CHANGED
package/src/Game.tsx
CHANGED
|
@@ -126,8 +126,6 @@ export default function Game({
|
|
|
126
126
|
const [isIPadProPortrait, setIsIPadProPortrait] = useState(false);
|
|
127
127
|
const [isIPadProLandscape, setIsIPadProLandscape] = useState(false);
|
|
128
128
|
const [isHorizontalLayout, setIsHorizontalLayout] = useState(false);
|
|
129
|
-
const [loadedImages, setLoadedImages] = useState<Set<string>>(new Set());
|
|
130
|
-
const [preloadQueue, setPreloadQueue] = useState<string[]>([]);
|
|
131
129
|
|
|
132
130
|
// ✅ адаптив под мобилки, планшеты и десктоп
|
|
133
131
|
useEffect(() => {
|
|
@@ -252,33 +250,9 @@ export default function Game({
|
|
|
252
250
|
const getRandomSix = (arr: ImageItem[]) =>
|
|
253
251
|
[...arr].sort(() => Math.random() - 0.5).slice(0, 6);
|
|
254
252
|
|
|
255
|
-
|
|
256
|
-
const preloadImage = (src: string): Promise<void> => {
|
|
257
|
-
return new Promise((resolve, reject) => {
|
|
258
|
-
const img = new Image();
|
|
259
|
-
img.onload = () => {
|
|
260
|
-
setLoadedImages(prev => new Set(prev).add(src));
|
|
261
|
-
resolve();
|
|
262
|
-
};
|
|
263
|
-
img.onerror = reject;
|
|
264
|
-
img.src = src;
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const preloadImages = async (urls: string[]) => {
|
|
269
|
-
// Загружаем с задержкой, чтобы не блокировать UI
|
|
270
|
-
const promises = urls.map(url => preloadImage(url));
|
|
271
|
-
await Promise.allSettled(promises);
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const startGame = async () => {
|
|
253
|
+
const startGame = () => {
|
|
275
254
|
if (!theme) return;
|
|
276
|
-
|
|
277
255
|
const selected = getRandomSix(themes[theme]);
|
|
278
|
-
|
|
279
|
-
// ✅ Предзагружаем текущие изображения с высоким приоритетом
|
|
280
|
-
await preloadImages(selected.map(item => item.src));
|
|
281
|
-
|
|
282
256
|
setFiles(selected);
|
|
283
257
|
setStarted(true);
|
|
284
258
|
setFinished(false);
|
|
@@ -286,13 +260,6 @@ export default function Game({
|
|
|
286
260
|
setScore(0);
|
|
287
261
|
setResultsTable([]);
|
|
288
262
|
setUsedHidden([]);
|
|
289
|
-
|
|
290
|
-
// ✅ Загружаем следующий раунд в фоне
|
|
291
|
-
const nextBatch = getRandomSix(
|
|
292
|
-
themes[theme].filter(item => !selected.includes(item))
|
|
293
|
-
);
|
|
294
|
-
preloadImages(nextBatch.map(item => item.src)); // Не ждем завершения
|
|
295
|
-
|
|
296
263
|
startRound(selected, [], true);
|
|
297
264
|
};
|
|
298
265
|
|
|
@@ -398,20 +365,20 @@ export default function Game({
|
|
|
398
365
|
|
|
399
366
|
return (
|
|
400
367
|
// ensure logo is positioned inside the square container
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
368
|
+
<div style={{ ...styles.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }}>
|
|
369
|
+
<picture>
|
|
370
|
+
<source
|
|
371
|
+
srcSet={window.origin + "/cloud/speakid/games/whatsmissing/logo.svg"}
|
|
372
|
+
type="image/svg+xml"
|
|
373
|
+
/>
|
|
374
|
+
<img
|
|
375
|
+
src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"}
|
|
376
|
+
alt="SPEAKID Logo"
|
|
377
|
+
style={styles.gmLogoImg}
|
|
378
|
+
loading="lazy"
|
|
379
|
+
/>
|
|
380
|
+
</picture>
|
|
381
|
+
</div>
|
|
415
382
|
);
|
|
416
383
|
},
|
|
417
384
|
[isMobile]
|
|
@@ -462,62 +429,62 @@ export default function Game({
|
|
|
462
429
|
}}
|
|
463
430
|
>
|
|
464
431
|
<div id="whats-missing-root">
|
|
465
|
-
|
|
432
|
+
{!isMobile && MemoizedLogo}
|
|
466
433
|
{/* ====== ИГРОВАЯ ЛОГИКА ====== */}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
434
|
+
{!theme && !started && (
|
|
435
|
+
<div style={styles.gmCenterScreen}>
|
|
436
|
+
<h1 style={styles.gmHeadline1}>WHAT'S MISSING?</h1>
|
|
437
|
+
<p style={styles.gmBodyM}>Select a theme:</p>
|
|
471
438
|
<div style={{ display: "flex", gap: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "8px" : "16px" }}>
|
|
472
|
-
|
|
439
|
+
{["animals", "food", "toys"].map((t) => (
|
|
473
440
|
<button key={t} style={{
|
|
474
441
|
...styles.gmButton,
|
|
475
442
|
padding: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "8px 12px" : "12px 24px",
|
|
476
443
|
fontSize: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "12px" : "16px",
|
|
477
444
|
minWidth: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "70px" : "auto"
|
|
478
445
|
}} onClick={() => setTheme(t as Theme)}>
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
446
|
+
{t === "animals" ? "🐶 Animals" : t === "food" ? "🍎 Food" : "🧸 Toys"}
|
|
447
|
+
</button>
|
|
448
|
+
))}
|
|
449
|
+
</div>
|
|
450
|
+
<div style={{ marginTop: 24 }}>
|
|
451
|
+
<p style={styles.gmBodyS}>Choose number of rounds:</p>
|
|
485
452
|
<div style={{ display: "flex", gap: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "6px" : "12px", marginTop: 8 }}>
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
453
|
+
{[3, 4, 5].map((n) => (
|
|
454
|
+
<button
|
|
455
|
+
key={n}
|
|
456
|
+
style={{
|
|
457
|
+
...styles.gmButton,
|
|
458
|
+
...(rounds === n ? styles.gmButtonActive : {}),
|
|
492
459
|
padding: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "6px 10px" : "12px 24px",
|
|
493
460
|
fontSize: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "12px" : "16px",
|
|
494
461
|
minWidth: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "40px" : "auto"
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
</div>
|
|
462
|
+
}}
|
|
463
|
+
onClick={() => setRounds(n)}
|
|
464
|
+
>
|
|
465
|
+
{n}
|
|
466
|
+
</button>
|
|
467
|
+
))}
|
|
502
468
|
</div>
|
|
503
469
|
</div>
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
470
|
+
</div>
|
|
471
|
+
)}
|
|
472
|
+
{theme && !started && (
|
|
473
|
+
<div style={styles.gmCenterScreen}>
|
|
474
|
+
<h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
|
|
475
|
+
<p style={styles.gmBodyM}>Rounds: {rounds}</p>
|
|
509
476
|
<button style={{
|
|
510
477
|
...styles.gmButton,
|
|
511
478
|
padding: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "8px 16px" : "12px 24px",
|
|
512
479
|
fontSize: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "14px" : "16px",
|
|
513
480
|
minWidth: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "120px" : "auto"
|
|
514
481
|
}} onClick={startGame}>
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
482
|
+
▶ Start game
|
|
483
|
+
</button>
|
|
484
|
+
</div>
|
|
485
|
+
)}
|
|
486
|
+
{finished && (
|
|
487
|
+
<div style={styles.gmCenterScreen}>
|
|
521
488
|
<h1 style={{
|
|
522
489
|
...styles.gmHeadline1,
|
|
523
490
|
marginTop: (isMobile && window.innerWidth > window.innerHeight) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) || isIPadMiniPortrait || isIPadMiniLandscape || isIPadAirPortrait || isIPadAirLandscape || isSurfaceDuoPortrait || isSurfaceDuoLandscape || isIPadProPortrait || isIPadProLandscape ? "0px" : styles.gmHeadline1.marginTop,
|
|
@@ -541,31 +508,31 @@ export default function Game({
|
|
|
541
508
|
marginTop: (isMobile && window.innerWidth > window.innerHeight) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) || isIPadMiniPortrait || isIPadMiniLandscape || isIPadAirPortrait || isIPadAirLandscape || isSurfaceDuoPortrait || isSurfaceDuoLandscape || isIPadProPortrait || isIPadProLandscape ? "0px" : "20px",
|
|
542
509
|
marginBottom: (isMobile && window.innerWidth > window.innerHeight) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) || isIPadMiniPortrait || isIPadMiniLandscape || isIPadAirPortrait || isIPadAirLandscape || isSurfaceDuoPortrait || isSurfaceDuoLandscape || isIPadProPortrait || isIPadProLandscape ? "4px" : "32px"
|
|
543
510
|
}}>
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
511
|
+
<thead>
|
|
512
|
+
<tr>
|
|
513
|
+
<th>Round</th>
|
|
514
|
+
<th>Your Answer</th>
|
|
515
|
+
<th>Correct</th>
|
|
516
|
+
<th>Result</th>
|
|
517
|
+
</tr>
|
|
518
|
+
</thead>
|
|
519
|
+
<tbody>
|
|
520
|
+
{resultsTable.map((r, i) => (
|
|
521
|
+
<tr key={i}>
|
|
522
|
+
<td style={styles.gmTableCell}>{r.round}</td>
|
|
523
|
+
<td style={styles.gmTableCell}>{r.answer || "—"}</td>
|
|
524
|
+
<td style={styles.gmTableCell}>{r.correct}</td>
|
|
525
|
+
<td style={styles.gmTableCell}>
|
|
526
|
+
{r.result === "correct"
|
|
527
|
+
? "✔ Correct"
|
|
528
|
+
: r.result === "almost"
|
|
529
|
+
? "◐ Almost (0.5)"
|
|
530
|
+
: "✘ Wrong"}
|
|
531
|
+
</td>
|
|
550
532
|
</tr>
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
<tr key={i}>
|
|
555
|
-
<td style={styles.gmTableCell}>{r.round}</td>
|
|
556
|
-
<td style={styles.gmTableCell}>{r.answer || "—"}</td>
|
|
557
|
-
<td style={styles.gmTableCell}>{r.correct}</td>
|
|
558
|
-
<td style={styles.gmTableCell}>
|
|
559
|
-
{r.result === "correct"
|
|
560
|
-
? "✔ Correct"
|
|
561
|
-
: r.result === "almost"
|
|
562
|
-
? "◐ Almost (0.5)"
|
|
563
|
-
: "✘ Wrong"}
|
|
564
|
-
</td>
|
|
565
|
-
</tr>
|
|
566
|
-
))}
|
|
567
|
-
</tbody>
|
|
568
|
-
</table>
|
|
533
|
+
))}
|
|
534
|
+
</tbody>
|
|
535
|
+
</table>
|
|
569
536
|
<div style={{
|
|
570
537
|
display: "flex",
|
|
571
538
|
gap: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "6px" : "12px",
|
|
@@ -577,23 +544,23 @@ export default function Game({
|
|
|
577
544
|
fontSize: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "12px" : "16px",
|
|
578
545
|
minWidth: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "80px" : "auto"
|
|
579
546
|
}} onClick={startGame}>
|
|
580
|
-
|
|
581
|
-
|
|
547
|
+
🔁 Play again
|
|
548
|
+
</button>
|
|
582
549
|
<button style={{
|
|
583
550
|
...styles.gmButton,
|
|
584
551
|
padding: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "6px 10px" : "12px 24px",
|
|
585
552
|
fontSize: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "12px" : "16px",
|
|
586
553
|
minWidth: (isMobile && window.innerWidth > window.innerHeight) || (isMobile && window.innerWidth <= 375 && window.innerHeight <= 667) || (window.innerWidth === 896 && window.innerHeight === 414) || (window.innerWidth === 844 && window.innerHeight === 390) || (window.innerWidth === 926 && window.innerHeight === 428) || (window.innerWidth === 932 && window.innerHeight === 430) ? "80px" : "auto"
|
|
587
554
|
}} onClick={exitGame}>
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
</div>
|
|
555
|
+
⬅️ Choose theme
|
|
556
|
+
</button>
|
|
591
557
|
</div>
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
558
|
+
</div>
|
|
559
|
+
)}
|
|
560
|
+
{started && !finished && (
|
|
561
|
+
<div style={styles.gmGameLayout}>
|
|
562
|
+
<div
|
|
563
|
+
style={{
|
|
597
564
|
minHeight: isMobile && window.innerWidth <= 375 && window.innerHeight <= 667
|
|
598
565
|
? "45px" // iPhone SE: еще более компактная высота
|
|
599
566
|
: (isMobile && window.innerWidth > window.innerHeight && window.innerHeight <= 428)
|
|
@@ -607,10 +574,10 @@ export default function Game({
|
|
|
607
574
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700
|
|
608
575
|
? "60px" // iPhone landscape и малые экраны: компактная высота
|
|
609
576
|
: "160px",
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
577
|
+
display: "flex",
|
|
578
|
+
flexDirection: "column",
|
|
579
|
+
justifyContent: "center",
|
|
580
|
+
alignItems: "center",
|
|
614
581
|
paddingTop: isMobile && window.innerWidth <= 375 && window.innerHeight <= 667
|
|
615
582
|
? "8px" // iPhone SE: поднимаем таймер еще выше
|
|
616
583
|
: (isMobile && window.innerWidth > window.innerHeight && window.innerHeight <= 428)
|
|
@@ -624,23 +591,23 @@ export default function Game({
|
|
|
624
591
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700
|
|
625
592
|
? "15px" // iPhone landscape и малые экраны: поднимаем выше
|
|
626
593
|
: "40px"
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
594
|
+
}}
|
|
595
|
+
>
|
|
596
|
+
{phase === "ready" && (
|
|
597
|
+
<>
|
|
598
|
+
<h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
|
|
599
|
+
<div style={styles.gmHourglass}>⏳</div>
|
|
600
|
+
</>
|
|
601
|
+
)}
|
|
602
|
+
{phase === "memorize" && (
|
|
603
|
+
<p style={{ ...styles.gmBodyM, color: "#10b981" }}>
|
|
604
|
+
MEMORIZE ({memorizeTime})
|
|
605
|
+
</p>
|
|
606
|
+
)}
|
|
607
|
+
{phase === "guess" && !answered && (
|
|
608
|
+
<p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
|
|
609
|
+
)}
|
|
610
|
+
</div>
|
|
644
611
|
{phase !== "ready" && (
|
|
645
612
|
<div
|
|
646
613
|
style={{
|
|
@@ -770,37 +737,15 @@ export default function Game({
|
|
|
770
737
|
}}
|
|
771
738
|
>
|
|
772
739
|
{!isHidden && (
|
|
773
|
-
<
|
|
774
|
-
{
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
backgroundSize: "200% 100%",
|
|
783
|
-
borderRadius: "inherit",
|
|
784
|
-
display: "flex",
|
|
785
|
-
justifyContent: "center",
|
|
786
|
-
alignItems: "center"
|
|
787
|
-
}} />
|
|
788
|
-
)}
|
|
789
|
-
<img
|
|
790
|
-
src={file.src}
|
|
791
|
-
alt={file.name}
|
|
792
|
-
// @ts-ignore - fetchpriority is a newer API
|
|
793
|
-
fetchpriority={loadedImages.has(file.src) ? "auto" : "high"}
|
|
794
|
-
onLoad={() => setLoadedImages(prev => new Set(prev).add(file.src))}
|
|
795
|
-
style={{
|
|
796
|
-
width: "100%",
|
|
797
|
-
height: "100%",
|
|
798
|
-
objectFit: "cover",
|
|
799
|
-
opacity: loadedImages.has(file.src) ? 1 : 0,
|
|
800
|
-
transition: "opacity 0.3s ease"
|
|
801
|
-
}}
|
|
802
|
-
/>
|
|
803
|
-
</div>
|
|
740
|
+
<img
|
|
741
|
+
src={file.src}
|
|
742
|
+
alt={file.name}
|
|
743
|
+
style={{
|
|
744
|
+
width: "100%",
|
|
745
|
+
height: "100%",
|
|
746
|
+
objectFit: "cover",
|
|
747
|
+
}}
|
|
748
|
+
/>
|
|
804
749
|
)}
|
|
805
750
|
</div>
|
|
806
751
|
);
|
|
@@ -835,7 +780,7 @@ export default function Game({
|
|
|
835
780
|
? "50px" // iPhone landscape и малые экраны: компактная высота
|
|
836
781
|
: "80px"
|
|
837
782
|
}}>
|
|
838
|
-
|
|
783
|
+
{phase === "guess" && !answered && (
|
|
839
784
|
<div style={{
|
|
840
785
|
display: "flex",
|
|
841
786
|
flexDirection: isHorizontalLayout ? "row" : "column",
|
|
@@ -890,11 +835,11 @@ export default function Game({
|
|
|
890
835
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700 ? "400px" : "300px"
|
|
891
836
|
}}>
|
|
892
837
|
<>
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
838
|
+
<input
|
|
839
|
+
type="text"
|
|
840
|
+
placeholder="Type the missing word"
|
|
841
|
+
value={inputValue}
|
|
842
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
898
843
|
style={{
|
|
899
844
|
...styles.gmInput,
|
|
900
845
|
width: isMobile && window.innerWidth <= 375 && window.innerHeight <= 667
|
|
@@ -968,8 +913,8 @@ export default function Game({
|
|
|
968
913
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700 ? "14px" : "16px",
|
|
969
914
|
flex: isHorizontalLayout ? "1" : "none"
|
|
970
915
|
}}
|
|
971
|
-
|
|
972
|
-
|
|
916
|
+
/>
|
|
917
|
+
<button
|
|
973
918
|
style={{
|
|
974
919
|
...styles.gmButton,
|
|
975
920
|
marginLeft: isHorizontalLayout ? "8px" : "0",
|
|
@@ -1044,15 +989,15 @@ export default function Game({
|
|
|
1044
989
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700 ? "80px" : "100px",
|
|
1045
990
|
flexShrink: 0
|
|
1046
991
|
}}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
992
|
+
onClick={checkAnswer}
|
|
993
|
+
disabled={animating}
|
|
994
|
+
>
|
|
995
|
+
{animating ? "..." : "Check"}
|
|
996
|
+
</button>
|
|
1052
997
|
</>
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
998
|
+
</div>
|
|
999
|
+
)}
|
|
1000
|
+
{answered && (
|
|
1056
1001
|
<button style={{
|
|
1057
1002
|
...styles.gmButton,
|
|
1058
1003
|
padding: isMobile && window.innerWidth <= 375 && window.innerHeight <= 667
|
|
@@ -1102,12 +1047,12 @@ export default function Game({
|
|
|
1102
1047
|
? "14px" // iPad и Surface DUO: размер шрифта кнопки Next round
|
|
1103
1048
|
: (isMobile && window.innerWidth > window.innerHeight) || window.innerHeight < 700 ? "14px" : "16px"
|
|
1104
1049
|
}} onClick={nextRound}>
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
</div>
|
|
1050
|
+
Next round
|
|
1051
|
+
</button>
|
|
1052
|
+
)}
|
|
1109
1053
|
</div>
|
|
1110
|
-
|
|
1054
|
+
</div>
|
|
1055
|
+
)}
|
|
1111
1056
|
</div>
|
|
1112
1057
|
</div>
|
|
1113
1058
|
</div>
|