From 97861a1084fadd6290306af67adc4e0128bbe927 Mon Sep 17 00:00:00 2001
From: Muhammed Kaplan <mmuhammedkaplan0@gmail.com>
Date: Sat, 26 Oct 2024 14:53:01 +0000
Subject: [PATCH] fix: make fullscreen mode trigger automatically

---
 readme.md            |   5 +-
 src/settings.js      | 437 ++++++++++++++++++++++++++-----------------
 src/windowManager.js |  81 +++++---
 3 files changed, 318 insertions(+), 205 deletions(-)

diff --git a/readme.md b/readme.md
index 5778f39..a3dceac 100644
--- a/readme.md
+++ b/readme.md
@@ -34,9 +34,8 @@ FX Client is the first Territorial.io client, offering a better User Interface a
 
 #### The client has a settings menu, from which you can:
 
-13. Make fullscreen mode trigger automatically
-14. Set a custom main menu background
-15. Create custom attack percentage keybinds
+13. Set a custom main menu background
+14. Create custom attack percentage keybinds
 
 ## Building Locally
 
diff --git a/src/settings.js b/src/settings.js
index a74575b..2fc54b1 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -6,204 +6,295 @@ window.__fx = window.__fx || {};
 const __fx = window.__fx;
 
 var settings = {
-    //"fontName": "Trebuchet MS",
-    //"showBotDonations": false,
-    "displayWinCounter": true,
-    "useFullscreenMode": false,
-    "hoveringTooltip": true,
-    //"hideAllLinks": false,
-    "realisticNames": false,
-    "showPlayerDensity": true,
-    "coloredDensity": true,
-    "densityDisplayStyle": "percentage",
-    "highlightClanSpawns": false,
-    //"customMapFileBtn": true
-    "customBackgroundUrl": "",
-    "attackPercentageKeybinds": [],
+  //"fontName": "Trebuchet MS",
+  //"showBotDonations": false,
+  displayWinCounter: true,
+  useFullscreenMode: false,
+  hoveringTooltip: true,
+  //"hideAllLinks": false,
+  realisticNames: false,
+  showPlayerDensity: true,
+  coloredDensity: true,
+  densityDisplayStyle: "percentage",
+  highlightClanSpawns: false,
+  //"customMapFileBtn": true
+  customBackgroundUrl: "",
+  attackPercentageKeybinds: [],
 };
 __fx.settings = settings;
-const discontinuedSettings = [ "hideAllLinks", "fontName" ];
+const discontinuedSettings = ["hideAllLinks", "fontName"];
 __fx.makeMainMenuTransparent = false;
 
 /*var settingsGearIcon = document.createElement('img');
 settingsGearIcon.setAttribute('src', 'assets/geari_white.png');*/
 
-const settingsManager = new (function() {
-    const settingsStructure = [
-        { for: "displayWinCounter", type: "checkbox", label: "Display win counter",
-            note: "The win counter tracks multiplayer solo wins (not in team games)" },
-        { type: "button", text: "Reset win counter", action: winCounter.removeWins },
-        { for: "useFullscreenMode", type: "checkbox", label: "Use fullscreen mode",
-        note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions." },
-        { for: "hoveringTooltip", type: "checkbox", label: "Hovering tooltip",
-        note: "Display map territory info constantly (on mouse hover) instead of only when right clicking on the map" },
-        //{ for: "hideAllLinks", type: "checkbox", label: "Hide Links option also hides app store links" },
-        { for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" },
-        { for: "showPlayerDensity", type: "checkbox", label: "Show player density" },
-        { for: "coloredDensity", type: "checkbox", label: "Colored density", note: "Display the density with a color between red and green depending on the density value" },
-        { for: "densityDisplayStyle", type: "selectMenu", label: "Density value display style:", tooltip: "Controls how the territorial density value should be rendered", options: [
-            { value: "percentage", label: "Percentage" },
-            { value: "absoluteQuotient", label: "Value from 0 to 150 (BetterTT style)" }
-        ]},
-        { for: "highlightClanSpawns", type: "checkbox", label: "Highlight clan spawnpoints",
-            note: "Increases the spawnpoint glow size for members of your clan" },
-        { for: "customBackgroundUrl", type: "textInput", label: "Custom main menu background:", placeholder: "Enter an image URL here", tooltip: "A custom image to be shown as the main menu background instead of the currently selected map." },
-        KeybindsInput
-    ];
-    const settingsContainer = document.querySelector(".settings .scrollable");
-    var inputFields = {}; // (includes select menus)
-    var checkboxFields = {};
-    var customElements = [];
-    settingsStructure.forEach(item => {
-        if (typeof item === "function") {
-            const container = document.createElement("div");
-            customElements.push(new item(container));
-            return settingsContainer.append(container);
-        }
-        const label = document.createElement("label");
-        if (item.tooltip) label.title = item.tooltip;
-        const isValueInput = item.type.endsWith("Input");
-        const element = document.createElement(isValueInput || item.type === "checkbox" ? "input" : item.type === "selectMenu" ? "select" : "button");
-        if (item.type === "textInput") element.type = "text";
-        if (item.placeholder) element.placeholder = item.placeholder;
-        if (isValueInput || item.type === "selectMenu") inputFields[item.for] = element;
-        if (item.text) element.innerText = item.text;
-        if (item.action) element.addEventListener("click", item.action);
-        if (item.label) label.append(item.label + " ");
-        if (item.note) {
-            const note = document.createElement("small");
-            note.innerText = item.note;
-            label.append(document.createElement("br"), note)
-        }
-        if (item.options) item.options.forEach(option => {
-            const optionElement = document.createElement("option");
-            optionElement.setAttribute("value", option.value);
-            optionElement.innerText = option.label;
-            element.append(optionElement);
-        });
-        label.append(element);
-        if (item.type === "checkbox") {
-            element.type = "checkbox";
-            const checkmark = document.createElement("span");
-            checkmark.className = "checkmark";
-            label.className = "checkbox";
-            label.append(checkmark);
-            checkboxFields[item.for] = element;
-        } else label.append(document.createElement("br"));
-        settingsContainer.append(label, document.createElement("br"));
+const settingsManager = new (function () {
+  const settingsStructure = [
+    {
+      for: "displayWinCounter",
+      type: "checkbox",
+      label: "Display win counter",
+      note: "The win counter tracks multiplayer solo wins (not in team games)",
+    },
+    {
+      type: "button",
+      text: "Reset win counter",
+      action: winCounter.removeWins,
+    },
+    {
+      for: "useFullscreenMode",
+      type: "checkbox",
+      label: "Use fullscreen mode",
+      note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions.",
+    },
+    {
+      for: "hoveringTooltip",
+      type: "checkbox",
+      label: "Hovering tooltip",
+      note: "Display map territory info constantly (on mouse hover) instead of only when right clicking on the map",
+    },
+    //{ for: "hideAllLinks", type: "checkbox", label: "Hide Links option also hides app store links" },
+    { for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" },
+    {
+      for: "showPlayerDensity",
+      type: "checkbox",
+      label: "Show player density",
+    },
+    {
+      for: "coloredDensity",
+      type: "checkbox",
+      label: "Colored density",
+      note: "Display the density with a color between red and green depending on the density value",
+    },
+    {
+      for: "densityDisplayStyle",
+      type: "selectMenu",
+      label: "Density value display style:",
+      tooltip: "Controls how the territorial density value should be rendered",
+      options: [
+        { value: "percentage", label: "Percentage" },
+        {
+          value: "absoluteQuotient",
+          label: "Value from 0 to 150 (BetterTT style)",
+        },
+      ],
+    },
+    {
+      for: "highlightClanSpawns",
+      type: "checkbox",
+      label: "Highlight clan spawnpoints",
+      note: "Increases the spawnpoint glow size for members of your clan",
+    },
+    {
+      for: "customBackgroundUrl",
+      type: "textInput",
+      label: "Custom main menu background:",
+      placeholder: "Enter an image URL here",
+      tooltip:
+        "A custom image to be shown as the main menu background instead of the currently selected map.",
+    },
+    KeybindsInput,
+  ];
+  const settingsContainer = document.querySelector(".settings .scrollable");
+  var inputFields = {}; // (includes select menus)
+  var checkboxFields = {};
+  var customElements = [];
+  settingsStructure.forEach((item) => {
+    if (typeof item === "function") {
+      const container = document.createElement("div");
+      customElements.push(new item(container));
+      return settingsContainer.append(container);
+    }
+    const label = document.createElement("label");
+    if (item.tooltip) label.title = item.tooltip;
+    const isValueInput = item.type.endsWith("Input");
+    const element = document.createElement(
+      isValueInput || item.type === "checkbox"
+        ? "input"
+        : item.type === "selectMenu"
+        ? "select"
+        : "button"
+    );
+    if (item.type === "textInput") element.type = "text";
+    if (item.placeholder) element.placeholder = item.placeholder;
+    if (isValueInput || item.type === "selectMenu")
+      inputFields[item.for] = element;
+    if (item.text) element.innerText = item.text;
+    if (item.action) element.addEventListener("click", item.action);
+    if (item.label) label.append(item.label + " ");
+    if (item.note) {
+      const note = document.createElement("small");
+      note.innerText = item.note;
+      label.append(document.createElement("br"), note);
+    }
+    if (item.options)
+      item.options.forEach((option) => {
+        const optionElement = document.createElement("option");
+        optionElement.setAttribute("value", option.value);
+        optionElement.innerText = option.label;
+        element.append(optionElement);
+      });
+    label.append(element);
+    if (item.type === "checkbox") {
+      element.type = "checkbox";
+      const checkmark = document.createElement("span");
+      checkmark.className = "checkmark";
+      label.className = "checkbox";
+      label.append(checkmark);
+      checkboxFields[item.for] = element;
+    } else label.append(document.createElement("br"));
+    settingsContainer.append(label, document.createElement("br"));
+  });
+  this.save = function () {
+    Object.keys(inputFields).forEach(function (key) {
+      settings[key] = inputFields[key].value.trim();
     });
-    this.save = function() {
-        Object.keys(inputFields).forEach(function(key) { settings[key] = inputFields[key].value.trim(); });
-        Object.keys(checkboxFields).forEach(function(key) { settings[key] = checkboxFields[key].checked; });
-        this.applySettings();
-        WindowManager.closeWindow("settings");
-        discontinuedSettings.forEach(settingName => delete settings[settingName]);
+    Object.keys(checkboxFields).forEach(function (key) {
+      settings[key] = checkboxFields[key].checked;
+    });
+    this.applySettings();
+    WindowManager.closeWindow("settings");
+    discontinuedSettings.forEach((settingName) => delete settings[settingName]);
+    localStorage.setItem("fx_settings", JSON.stringify(settings));
+    // should probably firgure out a way to do this without reloading - // You can't do it, localstorages REQUIRE you to reload
+    window.location.reload();
+  };
+
+  const fileInput = document.createElement("input");
+  fileInput.type = "file";
+  function handleFileSelect(event) {
+    const input = event.target;
+    /** @type {File} */
+    const selectedFile = input.files[0];
+    if (!selectedFile) return;
+
+    input.removeEventListener("change", handleFileSelect);
+    input.value = "";
+    if (!selectedFile.name.endsWith(".json"))
+      return alert("Invalid file format");
+    const fileReader = new FileReader();
+    fileReader.onload = function () {
+      let result;
+      try {
+        result = JSON.parse(fileReader.result);
+        if (
+          confirm(
+            'Warning: This will override all current settings, click "OK" to confirm'
+          )
+        )
+          __fx.settings = settings = result;
         localStorage.setItem("fx_settings", JSON.stringify(settings));
-        // should probably firgure out a way to do this without reloading - // You can't do it, localstorages REQUIRE you to reload
         window.location.reload();
+      } catch (error) {
+        alert("Error\n" + error);
+      }
     };
+    fileReader.readAsText(selectedFile);
+  }
+  this.importFromFile = function () {
+    fileInput.click();
+    fileInput.addEventListener("change", handleFileSelect);
+  };
+  // https://stackoverflow.com/a/34156339
+  function saveFile(content, fileName, contentType) {
+    var a = document.createElement("a");
+    var file = new Blob([content], { type: contentType });
+    a.href = URL.createObjectURL(file);
+    a.download = fileName;
+    a.click();
+    URL.revokeObjectURL(a.href);
+  }
+  this.exportToFile = function () {
+    saveFile(
+      JSON.stringify(settings),
+      "FX_client_settings.json",
+      "application/json"
+    );
+  };
 
-    const fileInput = document.createElement("input");
-    fileInput.type = "file";
-    function handleFileSelect(event) {
-        const input = event.target;
-        /** @type {File} */
-        const selectedFile = input.files[0];
-        if (!selectedFile) return;
+  this.syncFields = function () {
+    Object.keys(inputFields).forEach(function (key) {
+      inputFields[key].value = settings[key];
+    });
+    Object.keys(checkboxFields).forEach(function (key) {
+      checkboxFields[key].checked = settings[key];
+    });
+    customElements.forEach((element) => element.update(settings));
+  };
+  this.resetAll = function () {
+    if (
+      !confirm(
+        "Are you Really SURE you want to RESET ALL SETTINGS back to the default?"
+      )
+    )
+      return;
+    localStorage.removeItem("fx_settings");
+    window.location.reload();
+  };
+  this.applySettings = function () {
+    //setVarByName("bu", "px " + settings.fontName);
 
-        input.removeEventListener("change", handleFileSelect);
-        input.value = "";
-        if (!selectedFile.name.endsWith(".json")) return alert("Invalid file format");
-        const fileReader = new FileReader();
-        fileReader.onload = function() {
-            let result;
-            try {    
-                result = JSON.parse(fileReader.result);
-                if (confirm("Warning: This will override all current settings, click \"OK\" to confirm")) __fx.settings = settings = result;
-                localStorage.setItem("fx_settings", JSON.stringify(settings));
-                window.location.reload();
-            } catch (error) {
-                alert("Error\n" + error)
-            }
-        }
-        fileReader.readAsText(selectedFile);
+    if (settings.customBackgroundUrl !== "") {
+      document.body.style.backgroundImage =
+        "url(" + settings.customBackgroundUrl + ")";
+      document.body.style.backgroundSize = "cover";
+      document.body.style.backgroundPosition = "center";
     }
-    this.importFromFile = function() {
-        fileInput.click();
-        fileInput.addEventListener('change', handleFileSelect);
-    };
-    // https://stackoverflow.com/a/34156339
-    function saveFile(content, fileName, contentType) {
-        var a = document.createElement("a");
-        var file = new Blob([content], {type: contentType});
-        a.href = URL.createObjectURL(file);
-        a.download = fileName;
-        a.click();
-        URL.revokeObjectURL(a.href);
-    }
-    this.exportToFile = function() {
-        saveFile(JSON.stringify(settings), 'FX_client_settings.json', 'application/json');
-    };
+    __fx.makeMainMenuTransparent = settings.customBackgroundUrl !== "";
+  };
 
-    this.syncFields = function() {
-        Object.keys(inputFields).forEach(function(key) { inputFields[key].value = settings[key]; });
-        Object.keys(checkboxFields).forEach(function(key) { checkboxFields[key].checked = settings[key]; });
-        customElements.forEach(element => element.update(settings));
-    };
-    this.resetAll = function() {
-        if (!confirm("Are you Really SURE you want to RESET ALL SETTINGS back to the default?")) return;
-        localStorage.removeItem("fx_settings");
-        window.location.reload();
-    };
-    this.applySettings = function() {
-        //setVarByName("bu", "px " + settings.fontName);
-        if (settings.useFullscreenMode && document.fullscreenEnabled) {
-            function tryEnterFullscreen() {
-                if (document.fullscreenElement !== null) return;
-                document.documentElement.requestFullscreen({ navigationUI: "hide" })
-                    .then(() => { console.log('Fullscreen mode activated'); })
-                    .catch((error) => { console.warn('Could not enter fullscreen mode:', error); });
-            }
-            document.addEventListener('mousedown', tryEnterFullscreen, { once: true });
-            document.addEventListener('click', tryEnterFullscreen, { once: true });
-        }
-        if (settings.customBackgroundUrl !== "") {
-            document.body.style.backgroundImage = "url(" + settings.customBackgroundUrl + ")";
-            document.body.style.backgroundSize = "cover";
-            document.body.style.backgroundPosition = "center";
-        }
-        __fx.makeMainMenuTransparent = settings.customBackgroundUrl !== "";
-    };
-});
+  if (settings.useFullscreenMode && document.fullscreenEnabled) {
+    tryEnterFullscreen();
+  }
+})();
+
+export function tryEnterFullscreen() {
+  if (document.fullscreenElement !== null) return;
+  document.documentElement
+    .requestFullscreen({ navigationUI: "hide" })
+    .then(() => {
+      console.log("Fullscreen mode activated");
+    })
+    .catch((error) => {
+      console.warn("Could not enter fullscreen mode:", error);
+    });
+}
 
 const openCustomBackgroundFilePicker = () => {
-    const fileInput = document.getElementById("customBackgroundFileInput");
-    fileInput.click();
-    fileInput.addEventListener('change', handleFileSelect);
-}
+  const fileInput = document.getElementById("customBackgroundFileInput");
+  fileInput.click();
+  fileInput.addEventListener("change", handleFileSelect);
+};
 function handleFileSelect(event) {
-    const fileInput = event.target;
-    const selectedFile = fileInput.files[0];
-    console.log(fileInput.files);
-    console.log(fileInput.files[0]);
-    if (selectedFile) {
-        const fileUrl = URL.createObjectURL(selectedFile);
-        console.log("File URL:", fileUrl);
-        fileInput.value = "";
-        fileInput.removeEventListener("change", handleFileSelect);
-    }
+  const fileInput = event.target;
+  const selectedFile = fileInput.files[0];
+  console.log(fileInput.files);
+  console.log(fileInput.files[0]);
+  if (selectedFile) {
+    const fileUrl = URL.createObjectURL(selectedFile);
+    console.log("File URL:", fileUrl);
+    fileInput.value = "";
+    fileInput.removeEventListener("change", handleFileSelect);
+  }
 }
 
 WindowManager.add({
-    name: "settings",
-    element: document.querySelector(".settings"),
-    beforeOpen: function() { settingsManager.syncFields(); }
+  name: "settings",
+  element: document.querySelector(".settings"),
+  beforeOpen: function () {
+    settingsManager.syncFields();
+  },
 });
 
 if (localStorage.getItem("fx_settings") !== null) {
-    __fx.settings = settings = {...settings, ...JSON.parse(localStorage.getItem("fx_settings"))};
+  __fx.settings = settings = {
+    ...settings,
+    ...JSON.parse(localStorage.getItem("fx_settings")),
+  };
 }
 settingsManager.applySettings();
 
 export default settingsManager;
-export function getSettings() { return settings; };
\ No newline at end of file
+export function getSettings() {
+  return settings;
+}
diff --git a/src/windowManager.js b/src/windowManager.js
index 95ef9f4..20930c5 100644
--- a/src/windowManager.js
+++ b/src/windowManager.js
@@ -1,40 +1,63 @@
+import { getSettings, tryEnterFullscreen } from "./settings.js";
+
 var windows = {};
+
 const container = document.getElementById("windowContainer");
 function create(info) {
-    const window = document.createElement("div");
-    info.element = window;
-    window.className = "window" + (info.classes !== undefined ? " " + info.classes : " scrollable selectable");
-    window.style.display = "none";
-    container.appendChild(window);
-    add(info);
-    return window;
+  const window = document.createElement("div");
+  info.element = window;
+  window.className =
+    "window" +
+    (info.classes !== undefined
+      ? " " + info.classes
+      : " scrollable selectable");
+  window.style.display = "none";
+  container.appendChild(window);
+  add(info);
+  return window;
 }
 function add(newWindow) {
-    windows[newWindow.name] = newWindow;
-    windows[newWindow.name].isOpen = false;
-};
+  windows[newWindow.name] = newWindow;
+  windows[newWindow.name].isOpen = false;
+}
 function openWindow(windowName, ...args) {
-    if (windows[windowName].isOpen === true) return;
-    if (windows[windowName].beforeOpen !== undefined) windows[windowName].beforeOpen(...args);
-    windows[windowName].isOpen = true;
-    windows[windowName].element.style.display = null;
-};
+  if (windows[windowName].isOpen === true) return;
+  if (windows[windowName].beforeOpen !== undefined)
+    windows[windowName].beforeOpen(...args);
+  windows[windowName].isOpen = true;
+  windows[windowName].element.style.display = null;
+}
 function closeWindow(windowName) {
-    if (windows[windowName].isOpen === false) return;
-    windows[windowName].isOpen = false;
-    windows[windowName].element.style.display = "none";
-    if (windows[windowName].onClose !== undefined) windows[windowName].onClose();
-};
+  if (windows[windowName].isOpen === false) return;
+  windows[windowName].isOpen = false;
+  windows[windowName].element.style.display = "none";
+  if (windows[windowName].onClose !== undefined) windows[windowName].onClose();
+}
 function closeAll() {
-    Object.values(windows).forEach(function (windowObj) {
-        if (windowObj.closable !== false) closeWindow(windowObj.name);
-    });
-};
-document.addEventListener("mousedown", (e) => {
+  Object.values(windows).forEach(function (windowObj) {
+    if (windowObj.closable !== false) closeWindow(windowObj.name);
+  });
+}
+document.addEventListener(
+  "mousedown",
+  (e) => {
     // when clicking outside a window
     if (!container.contains(e.target)) closeAll();
-}, { passive: true, capture: true })
-document.getElementById("canvasA").addEventListener("touchstart", closeAll, { passive: true });
-document.addEventListener("keydown", event => { if (event.key === "Escape") closeAll(); });
 
-export default { create, add, openWindow, closeWindow, closeAll }
\ No newline at end of file
+    const isFullScreenEnabled = getSettings().useFullscreenMode;
+
+    if (isFullScreenEnabled) {
+      tryEnterFullscreen();
+    }
+  },
+  { passive: true, capture: true }
+);
+
+document
+  .getElementById("canvasA")
+  .addEventListener("touchstart", closeAll, { passive: true });
+document.addEventListener("keydown", (event) => {
+  if (event.key === "Escape") closeAll();
+});
+
+export default { create, add, openWindow, closeWindow, closeAll };