fix: make fullscreen mode trigger automatically (#6)

* fix: make fullscreen mode trigger automatically

* Small fix to check whether fullscreen mode is available

* revert: readme

* Bump version

---------

Co-authored-by: peshomir <80340328+peshomir@users.noreply.github.com>
main
Muhammed Kaplan 2024-10-26 21:58:02 +02:00 committed by GitHub
parent 12a4a8e937
commit 14bf32b846
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 317 additions and 205 deletions

View File

@ -1,5 +1,5 @@
const fx_version = '0.6.6.3'; // FX Client Version const fx_version = '0.6.6.4'; // FX Client Version
const fx_update = 'Oct 21'; // FX Client Last Updated const fx_update = 'Oct 26'; // FX Client Last Updated
import settingsManager from './settings.js'; import settingsManager from './settings.js';
import { clanFilter, leaderboardFilter } from "./clanFilters.js"; import { clanFilter, leaderboardFilter } from "./clanFilters.js";

View File

@ -6,204 +6,293 @@ window.__fx = window.__fx || {};
const __fx = window.__fx; const __fx = window.__fx;
var settings = { var settings = {
//"fontName": "Trebuchet MS", //"fontName": "Trebuchet MS",
//"showBotDonations": false, //"showBotDonations": false,
"displayWinCounter": true, displayWinCounter: true,
"useFullscreenMode": false, useFullscreenMode: false,
"hoveringTooltip": true, hoveringTooltip: true,
//"hideAllLinks": false, //"hideAllLinks": false,
"realisticNames": false, realisticNames: false,
"showPlayerDensity": true, showPlayerDensity: true,
"coloredDensity": true, coloredDensity: true,
"densityDisplayStyle": "percentage", densityDisplayStyle: "percentage",
"highlightClanSpawns": false, highlightClanSpawns: false,
//"customMapFileBtn": true //"customMapFileBtn": true
"customBackgroundUrl": "", customBackgroundUrl: "",
"attackPercentageKeybinds": [], attackPercentageKeybinds: [],
}; };
__fx.settings = settings; __fx.settings = settings;
const discontinuedSettings = [ "hideAllLinks", "fontName" ]; const discontinuedSettings = ["hideAllLinks", "fontName"];
__fx.makeMainMenuTransparent = false; __fx.makeMainMenuTransparent = false;
/*var settingsGearIcon = document.createElement('img'); /*var settingsGearIcon = document.createElement('img');
settingsGearIcon.setAttribute('src', 'assets/geari_white.png');*/ settingsGearIcon.setAttribute('src', 'assets/geari_white.png');*/
const settingsManager = new (function() { const settingsManager = new (function () {
const settingsStructure = [ const settingsStructure = [
{ for: "displayWinCounter", type: "checkbox", label: "Display win counter", {
note: "The win counter tracks multiplayer solo wins (not in team games)" }, for: "displayWinCounter",
{ type: "button", text: "Reset win counter", action: winCounter.removeWins }, type: "checkbox",
{ for: "useFullscreenMode", type: "checkbox", label: "Use fullscreen mode", label: "Display win counter",
note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions." }, note: "The win counter tracks multiplayer solo wins (not in team games)",
{ 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" }, type: "button",
{ for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" }, text: "Reset win counter",
{ for: "showPlayerDensity", type: "checkbox", label: "Show player density" }, action: winCounter.removeWins,
{ 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" }, for: "useFullscreenMode",
{ value: "absoluteQuotient", label: "Value from 0 to 150 (BetterTT style)" } type: "checkbox",
]}, label: "Use fullscreen mode",
{ for: "highlightClanSpawns", type: "checkbox", label: "Highlight clan spawnpoints", note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions.",
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 for: "hoveringTooltip",
]; type: "checkbox",
const settingsContainer = document.querySelector(".settings .scrollable"); label: "Hovering tooltip",
var inputFields = {}; // (includes select menus) note: "Display map territory info constantly (on mouse hover) instead of only when right clicking on the map",
var checkboxFields = {}; },
var customElements = []; //{ for: "hideAllLinks", type: "checkbox", label: "Hide Links option also hides app store links" },
settingsStructure.forEach(item => { { for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" },
if (typeof item === "function") { {
const container = document.createElement("div"); for: "showPlayerDensity",
customElements.push(new item(container)); type: "checkbox",
return settingsContainer.append(container); label: "Show player density",
} },
const label = document.createElement("label"); {
if (item.tooltip) label.title = item.tooltip; for: "coloredDensity",
const isValueInput = item.type.endsWith("Input"); type: "checkbox",
const element = document.createElement(isValueInput || item.type === "checkbox" ? "input" : item.type === "selectMenu" ? "select" : "button"); label: "Colored density",
if (item.type === "textInput") element.type = "text"; note: "Display the density with a color between red and green depending on the density value",
if (item.placeholder) element.placeholder = item.placeholder; },
if (isValueInput || item.type === "selectMenu") inputFields[item.for] = element; {
if (item.text) element.innerText = item.text; for: "densityDisplayStyle",
if (item.action) element.addEventListener("click", item.action); type: "selectMenu",
if (item.label) label.append(item.label + " "); label: "Density value display style:",
if (item.note) { tooltip: "Controls how the territorial density value should be rendered",
const note = document.createElement("small"); options: [
note.innerText = item.note; { value: "percentage", label: "Percentage" },
label.append(document.createElement("br"), note) {
} value: "absoluteQuotient",
if (item.options) item.options.forEach(option => { label: "Value from 0 to 150 (BetterTT style)",
const optionElement = document.createElement("option"); },
optionElement.setAttribute("value", option.value); ],
optionElement.innerText = option.label; },
element.append(optionElement); {
}); for: "highlightClanSpawns",
label.append(element); type: "checkbox",
if (item.type === "checkbox") { label: "Highlight clan spawnpoints",
element.type = "checkbox"; note: "Increases the spawnpoint glow size for members of your clan",
const checkmark = document.createElement("span"); },
checkmark.className = "checkmark"; {
label.className = "checkbox"; for: "customBackgroundUrl",
label.append(checkmark); type: "textInput",
checkboxFields[item.for] = element; label: "Custom main menu background:",
} else label.append(document.createElement("br")); placeholder: "Enter an image URL here",
settingsContainer.append(label, document.createElement("br")); 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(checkboxFields).forEach(function (key) {
Object.keys(inputFields).forEach(function(key) { settings[key] = inputFields[key].value.trim(); }); settings[key] = checkboxFields[key].checked;
Object.keys(checkboxFields).forEach(function(key) { settings[key] = checkboxFields[key].checked; }); });
this.applySettings(); this.applySettings();
WindowManager.closeWindow("settings"); WindowManager.closeWindow("settings");
discontinuedSettings.forEach(settingName => delete settings[settingName]); 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)); 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(); 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"); this.syncFields = function () {
fileInput.type = "file"; Object.keys(inputFields).forEach(function (key) {
function handleFileSelect(event) { inputFields[key].value = settings[key];
const input = event.target; });
/** @type {File} */ Object.keys(checkboxFields).forEach(function (key) {
const selectedFile = input.files[0]; checkboxFields[key].checked = settings[key];
if (!selectedFile) return; });
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); if (settings.customBackgroundUrl !== "") {
input.value = ""; document.body.style.backgroundImage =
if (!selectedFile.name.endsWith(".json")) return alert("Invalid file format"); "url(" + settings.customBackgroundUrl + ")";
const fileReader = new FileReader(); document.body.style.backgroundSize = "cover";
fileReader.onload = function() { document.body.style.backgroundPosition = "center";
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);
} }
this.importFromFile = function() { __fx.makeMainMenuTransparent = settings.customBackgroundUrl !== "";
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');
};
this.syncFields = function() { if (settings.useFullscreenMode) tryEnterFullscreen();
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)); export function tryEnterFullscreen() {
}; if (document.fullscreenElement !== null || !document.fullscreenEnabled) return;
this.resetAll = function() { document.documentElement
if (!confirm("Are you Really SURE you want to RESET ALL SETTINGS back to the default?")) return; .requestFullscreen({ navigationUI: "hide" })
localStorage.removeItem("fx_settings"); .then(() => {
window.location.reload(); console.log("Fullscreen mode activated");
}; })
this.applySettings = function() { .catch((error) => {
//setVarByName("bu", "px " + settings.fontName); console.warn("Could not enter fullscreen mode:", error);
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 !== "";
};
});
const openCustomBackgroundFilePicker = () => { const openCustomBackgroundFilePicker = () => {
const fileInput = document.getElementById("customBackgroundFileInput"); const fileInput = document.getElementById("customBackgroundFileInput");
fileInput.click(); fileInput.click();
fileInput.addEventListener('change', handleFileSelect); fileInput.addEventListener("change", handleFileSelect);
} };
function handleFileSelect(event) { function handleFileSelect(event) {
const fileInput = event.target; const fileInput = event.target;
const selectedFile = fileInput.files[0]; const selectedFile = fileInput.files[0];
console.log(fileInput.files); console.log(fileInput.files);
console.log(fileInput.files[0]); console.log(fileInput.files[0]);
if (selectedFile) { if (selectedFile) {
const fileUrl = URL.createObjectURL(selectedFile); const fileUrl = URL.createObjectURL(selectedFile);
console.log("File URL:", fileUrl); console.log("File URL:", fileUrl);
fileInput.value = ""; fileInput.value = "";
fileInput.removeEventListener("change", handleFileSelect); fileInput.removeEventListener("change", handleFileSelect);
} }
} }
WindowManager.add({ WindowManager.add({
name: "settings", name: "settings",
element: document.querySelector(".settings"), element: document.querySelector(".settings"),
beforeOpen: function() { settingsManager.syncFields(); } beforeOpen: function () {
settingsManager.syncFields();
},
}); });
if (localStorage.getItem("fx_settings") !== null) { 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(); settingsManager.applySettings();
export default settingsManager; export default settingsManager;
export function getSettings() { return settings; }; export function getSettings() {
return settings;
}

View File

@ -1,40 +1,63 @@
import { getSettings, tryEnterFullscreen } from "./settings.js";
var windows = {}; var windows = {};
const container = document.getElementById("windowContainer"); const container = document.getElementById("windowContainer");
function create(info) { function create(info) {
const window = document.createElement("div"); const window = document.createElement("div");
info.element = window; info.element = window;
window.className = "window" + (info.classes !== undefined ? " " + info.classes : " scrollable selectable"); window.className =
window.style.display = "none"; "window" +
container.appendChild(window); (info.classes !== undefined
add(info); ? " " + info.classes
return window; : " scrollable selectable");
window.style.display = "none";
container.appendChild(window);
add(info);
return window;
} }
function add(newWindow) { function add(newWindow) {
windows[newWindow.name] = newWindow; windows[newWindow.name] = newWindow;
windows[newWindow.name].isOpen = false; windows[newWindow.name].isOpen = false;
}; }
function openWindow(windowName, ...args) { function openWindow(windowName, ...args) {
if (windows[windowName].isOpen === true) return; if (windows[windowName].isOpen === true) return;
if (windows[windowName].beforeOpen !== undefined) windows[windowName].beforeOpen(...args); if (windows[windowName].beforeOpen !== undefined)
windows[windowName].isOpen = true; windows[windowName].beforeOpen(...args);
windows[windowName].element.style.display = null; windows[windowName].isOpen = true;
}; windows[windowName].element.style.display = null;
}
function closeWindow(windowName) { function closeWindow(windowName) {
if (windows[windowName].isOpen === false) return; if (windows[windowName].isOpen === false) return;
windows[windowName].isOpen = false; windows[windowName].isOpen = false;
windows[windowName].element.style.display = "none"; windows[windowName].element.style.display = "none";
if (windows[windowName].onClose !== undefined) windows[windowName].onClose(); if (windows[windowName].onClose !== undefined) windows[windowName].onClose();
}; }
function closeAll() { function closeAll() {
Object.values(windows).forEach(function (windowObj) { Object.values(windows).forEach(function (windowObj) {
if (windowObj.closable !== false) closeWindow(windowObj.name); if (windowObj.closable !== false) closeWindow(windowObj.name);
}); });
}; }
document.addEventListener("mousedown", (e) => { document.addEventListener(
"mousedown",
(e) => {
// when clicking outside a window // when clicking outside a window
if (!container.contains(e.target)) closeAll(); 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 } 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 };