@@ -33,6 +33,7 @@ import { UndoManager } from "./manager/undo";
33
33
import { AssetManager } from "./manager/asset" ;
34
34
import { formatTilesetName } from "./util/format" ;
35
35
import * as marked from "marked" ;
36
+ import { FullscreenManager } from "./manager/fullscreen" ;
36
37
37
38
import "./styles/global.css" ;
38
39
@@ -61,11 +62,13 @@ const ANIMATIONS_PREFERENCE_NAME = "animations";
61
62
const BLOCK_STYLE_PREFERENCE_NAME = "block" ;
62
63
const DEBUG_HUD_ENABLED_PREFERENCE_NAME = "debugHudEnabled" ;
63
64
const DEBUG_HUD_VISIBLE_PREFERENCE_NAME = "debugHudVisible" ;
65
+ const FULLSCREEN_PREFERENCE_NAME = "fullscreen" ;
64
66
65
67
const THEME_SETTING_NAME = "theme-switch" ;
66
68
const TILESET_SETTING_NAME = "tileset-switch" ;
67
69
const ANIMATIONS_SETTING_NAME = "animations" ;
68
70
const BLOCK_STYLE_SETTING_NAME = "block" ;
71
+ const FULLSCREEN_SETTING_NAME = "fullscreen" ;
69
72
const CLEAR_DATA_SETTING_NAME = "clear-all-data" ;
70
73
71
74
const SETTING_ENABLED = "enabled" ;
@@ -101,6 +104,7 @@ document.addEventListener("DOMContentLoaded", async () => {
101
104
let animationManager = new AnimationManager ( ) ;
102
105
let undoManager = new UndoManager ( ) ;
103
106
let gameStorage = new BrowserGameStorage ( ) ;
107
+ let fullscreenManager = new FullscreenManager ( gameStorage ) ;
104
108
let assetManager = new AssetManager ( document . querySelector ( ".loader-wrapper" ) as HTMLElement ) ;
105
109
// Store unlockable statuses so that their unlock messages don't display again if player achieved the same conditions again
106
110
let unlockedClassic = false ;
@@ -111,6 +115,9 @@ document.addEventListener("DOMContentLoaded", async () => {
111
115
112
116
const swipeSensitivity = 50 ;
113
117
118
+ const md = new MobileDetect ( window . navigator . userAgent ) ;
119
+ const isMobile = md . mobile ( ) !== null ;
120
+
114
121
const eventHandler = ( event : string , data : any ) => {
115
122
switch ( event ) {
116
123
case "init" :
@@ -292,6 +299,16 @@ document.addEventListener("DOMContentLoaded", async () => {
292
299
} ) ;
293
300
return ;
294
301
}
302
+ if ( key === "f" && ! isMobile ) {
303
+ fullscreenManager . toggleFullscreen ( ) ;
304
+ const knob = document . querySelector ( ".setting.fullscreen .knob" ) as HTMLElement ;
305
+ if ( fullscreenManager . isFullscreenEnabled ( ) ) {
306
+ knob . classList . add ( "enabled" ) ;
307
+ } else {
308
+ knob . classList . remove ( "enabled" ) ;
309
+ }
310
+ return ;
311
+ }
295
312
if ( gameState . ended ) {
296
313
return ;
297
314
}
@@ -325,6 +342,14 @@ document.addEventListener("DOMContentLoaded", async () => {
325
342
handleKeyInput ( e . key . toLowerCase ( ) ) ;
326
343
} ) ;
327
344
345
+ document . addEventListener ( "fullscreenchange" , ( ) => {
346
+ if ( ! document . fullscreenElement ) {
347
+ fullscreenManager . setFullscreenPreference ( false ) ;
348
+ const knob = document . querySelector ( ".setting.fullscreen .knob" ) as HTMLElement ;
349
+ knob . classList . remove ( "enabled" ) ;
350
+ }
351
+ } ) ;
352
+
328
353
const promptNewGame = ( onNewGameStarted ?: ( ) => void ) => {
329
354
// If game ended, no need to prompt
330
355
if ( gameState . ended ) {
@@ -348,6 +373,31 @@ document.addEventListener("DOMContentLoaded", async () => {
348
373
} ) ;
349
374
} ;
350
375
376
+ const promptFullscreen = ( ) => {
377
+ const dialogElem = createDialogContentFromTemplate ( "#prompt-dialog-content" ) ;
378
+ ( dialogElem . querySelector ( ".prompt-text" ) as HTMLSpanElement ) . innerText =
379
+ "Fullscreen mode is enabled. Do you want to turn it on?" ;
380
+ renderPromptDialog ( dialogElem , {
381
+ fadeIn : true ,
382
+ onConfirm : ( ) => {
383
+ fullscreenManager . toggleFullscreen ( true ) ;
384
+ const setting = document . querySelector (
385
+ `.setting.${ FULLSCREEN_SETTING_NAME } `
386
+ ) as HTMLElement ;
387
+ const knob = setting . querySelector ( ".knob" ) as HTMLElement ;
388
+ knob . classList . add ( "enabled" ) ;
389
+ } ,
390
+ onCancel : ( ) => {
391
+ fullscreenManager . toggleFullscreen ( false ) ;
392
+ const setting = document . querySelector (
393
+ `.setting.${ FULLSCREEN_SETTING_NAME } `
394
+ ) as HTMLElement ;
395
+ const knob = setting . querySelector ( ".knob" ) as HTMLElement ;
396
+ knob . classList . remove ( "enabled" ) ;
397
+ } ,
398
+ } ) ;
399
+ } ;
400
+
351
401
const helpLink = document . querySelector ( ".help-link" ) as HTMLElement ;
352
402
helpLink . addEventListener ( "click" , ( e ) => {
353
403
e . preventDefault ( ) ;
@@ -594,6 +644,14 @@ document.addEventListener("DOMContentLoaded", async () => {
594
644
switchBlockStyle ( nextBlockStyle ) ;
595
645
savePreferenceValue ( BLOCK_STYLE_PREFERENCE_NAME , nextBlockStyle ) ;
596
646
toggle . innerText = nextBlockStyle ;
647
+ } else if ( elem . classList . contains ( FULLSCREEN_SETTING_NAME ) ) {
648
+ fullscreenManager . toggleFullscreen ( ) ;
649
+ const knob = setting . querySelector ( ".knob" ) as HTMLElement ;
650
+ if ( fullscreenManager . isFullscreenEnabled ( ) ) {
651
+ knob . classList . add ( "enabled" ) ;
652
+ } else {
653
+ knob . classList . remove ( "enabled" ) ;
654
+ }
597
655
} else if ( elem . classList . contains ( CLEAR_DATA_SETTING_NAME ) ) {
598
656
const dialogElem = createDialogContentFromTemplate ( "#prompt-dialog-content" ) ;
599
657
( dialogElem . querySelector ( ".prompt-text" ) as HTMLSpanElement ) . innerHTML =
@@ -616,6 +674,12 @@ document.addEventListener("DOMContentLoaded", async () => {
616
674
} ) ;
617
675
} ) ;
618
676
677
+ // Hide fullscreen setting on mobile devices
678
+ const fullscreenOption = document . querySelector ( ".setting.fullscreen" ) as HTMLElement ;
679
+ if ( isMobile ) {
680
+ fullscreenOption . style . display = "none" ;
681
+ }
682
+
619
683
initPreferences ( gameStorage , {
620
684
[ ANIMATIONS_PREFERENCE_NAME ] : SETTING_ENABLED ,
621
685
} ) ;
@@ -650,6 +714,9 @@ document.addEventListener("DOMContentLoaded", async () => {
650
714
`.setting.${ BLOCK_STYLE_SETTING_NAME } `
651
715
) as HTMLElement ;
652
716
( blockStyleSetting . querySelector ( ".toggle" ) as HTMLElement ) . innerText = selectedBlockStyle ;
717
+ if ( getPreferenceValue ( FULLSCREEN_PREFERENCE_NAME ) === SETTING_ENABLED ) {
718
+ promptFullscreen ( ) ;
719
+ }
653
720
654
721
const generateShareText = ( gameState : GameState ) => {
655
722
return `I got a score of ${ gameState . score } in 2048-clone${
0 commit comments