From 0ae09121c03e554af64ffced6804cadad6a98e66 Mon Sep 17 00:00:00 2001 From: Saif Addin Date: Sat, 17 Apr 2021 02:38:56 +0200 Subject: [PATCH] Refactored relative positioning of macro and sidebar. Dynamic Minimal UI --- CHANGELOG.md | 7 ++ README.md | 6 +- minimalui.js | 232 ++++++++++++++++++++++++++++++++++----------------- module.json | 2 +- 4 files changed, 168 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31335bd..57a0251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### 0.6.0 +* Enhancement: NEW (Optional) Dynamic Minimal UI mode. After 60 seconds of inactivity, + UI will dynamically auto-hide until used or when switching Scenes. Check it out! (Experimental) +* Enhancement: Vertical positioning of Sidebar and Horizontal position of Macro now globally adjusted based on + actual canvas size. Users on different screens should have similar experiences. +* Compatibility: Fixed bug in Foundry that didn't show the chat when clicked if sidebar was collapsed + ### 0.5.7 * Compatibility: Works around a bug in Foundry that prevents opening windows when sidebar is collapsed diff --git a/README.md b/README.md index 93f5eaa..6d0c403 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ Configurable UI module, allows the user to hide, collapse or auto-hide component This includes hiding Foundry's Logo, Players List, Scene Navigation and Macro Bar. +### Special Minimal UI Features +* MINIMAL UI Dynamic Mode (Default: OFF): Auto-Hides UI elements after Chat inactivity or when + switching scenes. This allows making up space intelligently for you to save space. +* MINIMAL UI Organized Minimize (Default: OFF): + ### Foundry Logo * Foundry Logo may be hidden or resized * Can be made clickable to toggle show/hide HUD (Including chat or not) @@ -36,7 +41,6 @@ This includes hiding Foundry's Logo, Players List, Scene Navigation and Macro Ba * Default settings target a balance between gaining space and functionality * Colors of borders and shadows and their strength customizable * Position of elements in the UI can be modified -* Allows fixing the minimized window to a certain Axis to find them easily ## Support with Systems and Modules MinimalUI is made as agnostic as possible. Yet, it is impossible to ensure maximum compatibility. diff --git a/minimalui.js b/minimalui.js index 737e04b..ec14b4e 100644 --- a/minimalui.js +++ b/minimalui.js @@ -2,15 +2,16 @@ class MinimalUI { static hiddenInterface = false; static fakeDisabled = false; - + static lastHoverTime; + static hotbarLocked = false; static controlsLocked = false; static cssControlsLastPos = '0px'; - + static cssLeftBarStartVisible = '0px'; static cssLeftBarHiddenPositionSmall = '-62px'; static cssLeftBarHiddenPositionStandard = '-72px'; - + static cssLeftBarSubMenuSmall = '55px'; static cssLeftBarSubMenuStandard = '65px'; static cssLeftBarSubMenuDndUi = '65px'; @@ -24,11 +25,6 @@ class MinimalUI { static cssLeftBarSmallLineHeight = '30px'; static cssLeftBarSmallFontSize = '15px'; - static cssLeftBarVerticalPositionTop = '8vmin'; - static cssLeftBarVerticalPositionCenter = '20vmin'; - static cssLeftBarVerticalPositionLower = '30vmin'; - static cssLeftBarVerticalPositionBottom = '40vmin'; - static cssHotbarHidden = '-48px'; static cssHotbarReveal = '1px'; static cssHotbarShown = '10px'; @@ -46,8 +42,6 @@ class MinimalUI { static cssSceneNavStandardLogoStart = '125px'; static cssSceneNavBullseyeStart = '125px'; - static cssMinimumMacroBarX = 170; - static cssPlayersDefaultFontSize = '12px'; static cssPlayersDefaultWidth = '150px'; static cssPlayersDefaultWidthDnDUi = '200px'; @@ -148,6 +142,48 @@ class MinimalUI { } } + static positionHotbar() { + let rootStyle = document.querySelector(':root').style; + let availableWidth = parseInt($("#board").css('width')); + switch(game.settings.get('minimal-ui', 'macroBarPosition')) { + case 'left': { + rootStyle.setProperty('--macrobarxpos', ((availableWidth/2.5)-(availableWidth/9)-(availableWidth/9))+'px'); + break; + } + case 'center': { + rootStyle.setProperty('--macrobarxpos', ((availableWidth/2.5)-(availableWidth/9))+'px'); + break; + } + case 'right': { + rootStyle.setProperty('--macrobarxpos', ((availableWidth/2.5))+'px'); + break; + } + } + } + + static positionSidebar() { + let rootStyle = document.querySelector(':root').style; + let availableHeight = parseInt($("#board").css('height')); + switch(true) { + case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'top' || game.settings.get('minimal-ui', 'sidePanelMenuStyle') == 'column'): { + rootStyle.setProperty('--leftbarypos', ((availableHeight/3)-(availableHeight/9)-(availableHeight/9))+'px'); + break; + } + case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'center'): { + rootStyle.setProperty('--leftbarypos', ((availableHeight/3)-(availableHeight/9))+'px'); + break; + } + case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'lower'): { + rootStyle.setProperty('--leftbarypos', ((availableHeight/3))+'px'); + break; + } + case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'bottom'): { + rootStyle.setProperty('--leftbarypos', ((availableHeight/3)+(availableHeight/9))+'px'); + break; + } + } + } + static addLockButton() { let locked = MinimalUI.controlsLocked ? 'fa-lock' : 'fa-lock-open'; let htmlSidebarLockButton = @@ -177,6 +213,39 @@ Hooks.once('init', () => { } }); + game.settings.register('minimal-ui', 'dynamicMinimalUi', { + name: "MINIMAL UI Dynamic Mode", + hint: "Auto hides UI elements after 60 seconds of chat inactivity when controlling tokens or changing scenes (Experimental).", + scope: 'world', + config: true, + type: String, + choices: { + "enabled": "Enabled", + "disabled": "Disabled" + }, + default: "disabled", + onChange: value => { + window.location.reload() + } + }); + + game.settings.register('minimal-ui', 'organizedMinimize', { + name: "MINIMAL UI Organized Minimize", + hint: "This option may help you organize those minimized windows by placing them either on a bottom line or top bar(Experimental).", + scope: 'world', + config: true, + type: String, + choices: { + "bottom": "Bottom", + "top": "Top", + "disabled": "Disabled" + }, + default: "disabled", + onChange: value => { + window.location.reload() + } + }); + game.settings.register('minimal-ui', 'foundryLogoSize', { name: "Foundry Logo Size", hint: "Foundry logo visibility and size", @@ -210,23 +279,6 @@ Hooks.once('init', () => { } }); - game.settings.register('minimal-ui', 'organizedMinimize', { - name: "Foundry Organized Minimize", - hint: "This option may help you organize those minimized windows (Experimental).", - scope: 'world', - config: true, - type: String, - choices: { - "bottom": "Bottom", - "top": "Top", - "disabled": "Disabled" - }, - default: "disabled", - onChange: value => { - window.location.reload() - } - }); - game.settings.register('minimal-ui', 'rightSidePanel', { name: "Right Side Panel Behaviour", hint: "Whether the right side panel starts collapsed or not", @@ -237,7 +289,7 @@ Hooks.once('init', () => { "shown": "Shown", "collapsed": "Collapsed" }, - default: "shown", + default: "collapsed", onChange: value => { window.location.reload() } @@ -342,11 +394,16 @@ Hooks.once('init', () => { game.settings.register('minimal-ui', 'macroBarPosition', { name: "Macro Bar Position", - hint: `Reference at 400. Minimum is ${MinimalUI.cssMinimumMacroBarX}. Increase value to move it to right. Reduce to the left.`, + hint: `Horizontal position of the Macro Hotbar`, scope: 'world', config: true, - type: Number, - default: 400, + type: String, + choices: { + "left": "Center Left", + "center": "Center", + "right": "Center Right" + }, + default: "center", onChange: value => { window.location.reload() } @@ -401,35 +458,35 @@ Hooks.once('init', () => { } }); - game.settings.register('minimal-ui', 'sidePanelPosition', { - name: "Left panel position", - hint: "Choose favorite side panel position. Will be ignored if using 'Keep a single column' style.", + game.settings.register('minimal-ui', 'sidePanelMenuStyle', { + name: "Left panel menu style", + hint: "Choose whether to expand to the right or keep a single column of buttons", scope: 'world', config: true, type: String, choices: { - "top": "Top Left", - "center": "Center Upper Left", - "lower": "Center Lower Left", - "bottom": "Bottom Left" + "default": "Controls to the right", + "column": "Keep a single column" }, - default: "center", + default: "default", onChange: value => { window.location.reload() } }); - game.settings.register('minimal-ui', 'sidePanelMenuStyle', { - name: "Left panel menu style", - hint: "Choose whether to expand to the right or keep a single column of buttons", + game.settings.register('minimal-ui', 'sidePanelPosition', { + name: "Left panel position", + hint: "Choose favorite side panel position. Will be ignored if using 'Keep a single column' style.", scope: 'world', config: true, type: String, choices: { - "default": "Controls to the right", - "column": "Keep a single column" + "top": "Top Left", + "center": "Center Upper Left", + "lower": "Center Lower Left", + "bottom": "Bottom Left" }, - default: "default", + default: "center", onChange: value => { window.location.reload() } @@ -453,6 +510,11 @@ Hooks.once('init', () => { }); +Hooks.on('canvasPan', function() { + MinimalUI.positionHotbar(); + MinimalUI.positionSidebar(); +}); + Hooks.once('ready', async function() { let rootStyle = document.querySelector(':root').style; @@ -484,6 +546,12 @@ Hooks.once('ready', async function() { } } + MinimalUI.positionHotbar(); + + if (game.settings.get('minimal-ui', 'macroBar') != 'hidden') { + rootStyle.setProperty('--macrobarvis', 'visible'); + } + // Compatibility Workaround for bullseye module if (game.modules.has('bullseye') && game.modules.get('bullseye').active) { rootStyle.setProperty('--navixpos', MinimalUI.cssSceneNavBullseyeStart); @@ -506,13 +574,53 @@ Hooks.once('ready', async function() { // Temporarily work around a bug in Foundry VTT 0.7.9 $("#sidebar-tabs > a:nth-child(n)").click(function(eve) { + const tabName = jQuery(eve.currentTarget).attr('data-tab'); if (ui.sidebar._collapsed) { - ui.sidebar.activateTab(jQuery(eve.currentTarget).attr('data-tab')) + if (tabName == 'chat') { + ui.sidebar.expand(); + } else { + ui.sidebar.activateTab(tabName); + } } }) }); +Hooks.on('hoverToken', function() { + if (game.settings.get('minimal-ui', 'dynamicMinimalUi') == 'enabled') { + if (game.time.serverTime - MinimalUI.lastHoverTime > 60000) { + ui.sidebar.collapse(); + if (game.settings.get('minimal-ui', 'sidePanel') == 'autohide' && MinimalUI.controlsLocked) { + MinimalUI.lockControls(true); + } + MinimalUI.lastHoverTime = game.time.serverTime; + } + } +}); + +Hooks.on('canvasInit', function() { + if (game.settings.get('minimal-ui', 'dynamicMinimalUi') == 'enabled' && MinimalUI.lastHoverTime) { + ui.sidebar.collapse(); + if (game.settings.get('minimal-ui', 'sidePanel') == 'autohide' && MinimalUI.controlsLocked) { + MinimalUI.lockControls(true); + } + } +}); + +Hooks.on('renderChatMessage', function() { + if (game.settings.get('minimal-ui', 'dynamicMinimalUi') == 'enabled') { + MinimalUI.lastHoverTime = game.time.serverTime; + ui.sidebar.activateTab('chat'); + ui.sidebar.expand(); + } +}); + +Hooks.on('sidebarCollapse', function(_, collapsed) { + if (game.settings.get('minimal-ui', 'dynamicMinimalUi') == 'enabled' && !collapsed) { + MinimalUI.lastHoverTime = game.time.serverTime; + } +}) + Hooks.on('renderCameraViews', async function() { switch(game.settings.get('minimal-ui', 'hidePlayerCameras')) { case 'hidden': { @@ -715,16 +823,8 @@ Hooks.on('renderHotbar', async function() { let rootStyle = document.querySelector(':root').style; - let mbPos = game.settings.get('minimal-ui', 'macroBarPosition'); - if (mbPos < MinimalUI.cssMinimumMacroBarX) { - rootStyle.setProperty('--macrobarxpos', String(MinimalUI.cssMinimumMacroBarX)+'px'); - } else { - rootStyle.setProperty('--macrobarxpos', String(mbPos)+'px'); - } - switch(game.settings.get('minimal-ui', 'macroBar')) { case 'collapsed': { - rootStyle.setProperty('--macrobarvis', 'visible'); MinimalUI.collapseById("bar-toggle"); if (game.modules.has("custom-hotbar") && game.modules.get('custom-hotbar').active) { MinimalUI.collapseById("custom-bar-toggle"); @@ -751,11 +851,6 @@ Hooks.on('renderHotbar', async function() { } } $("#bar-toggle").remove(); - rootStyle.setProperty('--macrobarvis', 'visible'); - break; - } - case 'shown': { - rootStyle.setProperty('--macrobarvis', 'visible'); break; } } @@ -834,24 +929,7 @@ Hooks.once('renderSceneControls', async function() { }; // --- - switch(true) { - case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'top' || game.settings.get('minimal-ui', 'sidePanelMenuStyle') == 'column'): { - rootStyle.setProperty('--leftbarypos', MinimalUI.cssLeftBarVerticalPositionTop); - break; - } - case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'center'): { - rootStyle.setProperty('--leftbarypos', MinimalUI.cssLeftBarVerticalPositionCenter); - break; - } - case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'lower'): { - rootStyle.setProperty('--leftbarypos', MinimalUI.cssLeftBarVerticalPositionLower); - break; - } - case (game.settings.get('minimal-ui', 'sidePanelPosition') == 'bottom'): { - rootStyle.setProperty('--leftbarypos', MinimalUI.cssLeftBarVerticalPositionBottom); - break; - } - } + MinimalUI.positionSidebar(); switch(game.settings.get('minimal-ui', 'sidePanelMenuStyle')) { case 'default': { diff --git a/module.json b/module.json index 1631095..dfbcce7 100644 --- a/module.json +++ b/module.json @@ -3,7 +3,7 @@ "title": "Minimal UI", "author": "JeansenVaars#2857", "description": "Minimal UI reduces size of Foundry interface and allows hiding or collapsing specific parts.", - "version": "0.5.7", + "version": "0.6.0", "minimumCoreVersion": "0.7.9", "compatibleCoreVersion": "0.7.9", "esmodules": [ "lib/colorsettings/colorSetting.js" ],