From b0fdf1f63dedf5a8d060ee24d9d05ed6a9e204f4 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sun, 29 Jun 2025 14:21:40 -0700 Subject: [PATCH] Implement the basics of a dynamic toolbar Dynamic toolbar will hide and show automatically depending on user actions and state of the app. This is to save screen real estate. --- src/gui/src/UI/UIDesktop.js | 167 +++++++++++++++++++++++++++++++++++- src/gui/src/UI/UIWindow.js | 3 + src/gui/src/css/style.css | 41 +++++---- src/gui/src/globals.js | 2 +- src/gui/src/initgui.js | 5 ++ 5 files changed, 197 insertions(+), 21 deletions(-) diff --git a/src/gui/src/UI/UIDesktop.js b/src/gui/src/UI/UIDesktop.js index b07bf9c1a..57a0446ee 100644 --- a/src/gui/src/UI/UIDesktop.js +++ b/src/gui/src/UI/UIDesktop.js @@ -1148,7 +1148,7 @@ async function UIDesktop(options) { // User options // ---------------------------------------------------- let ht = ''; - ht += `
`; + ht += `
`; // logo ht += ``; @@ -1467,6 +1467,171 @@ async function UIDesktop(options) { app: 'explorer', }); } + + window.hide_toolbar = () => { + if ($('.toolbar').hasClass('toolbar-hidden')) return; + + // attach hidden class to toolbar + $('.toolbar').addClass('toolbar-hidden'); + + // animate the toolbar to top = -20px; + // animate width to 40px; + $('.toolbar').animate({ + top: '-20px', + width: '40px', + }, 200); + + // animate hide toolbar-btn, toolbar-clock + $('.toolbar-btn, #clock').animate({ + opacity: 0, + }, 50); + } + + window.show_toolbar = () => { + if (!$('.toolbar').hasClass('toolbar-hidden')) return; + + // remove hidden class from toolbar + $('.toolbar').removeClass('toolbar-hidden'); + + $('.toolbar').animate({ + top: 0, + }, 100).css('width', 'fit-content'); + + // animate show toolbar-btn, toolbar-clock + $('.toolbar-btn, #clock').animate({ + opacity: 0.8, + }, 50); + } + + // Toolbar hide/show logic with improved UX + let toolbarHideTimeout = null; + let isMouseNearToolbar = false; + + // Define safe zone around toolbar (in pixels) + const TOOLBAR_SAFE_ZONE = 50; + const TOOLBAR_HIDE_DELAY = 100; // Base delay before hiding + const TOOLBAR_QUICK_HIDE_DELAY = 300; // Quicker hide when mouse moves far away + + // Function to check if mouse is in the safe zone around toolbar + window.isMouseInToolbarSafeZone = (mouseX, mouseY) => { + const toolbar = $('.toolbar')[0]; + if (!toolbar) return false; + + const rect = toolbar.getBoundingClientRect(); + + // Expand the toolbar bounds by the safe zone + const safeZone = { + top: rect.top - TOOLBAR_SAFE_ZONE, + bottom: rect.bottom + TOOLBAR_SAFE_ZONE, + left: rect.left - TOOLBAR_SAFE_ZONE, + right: rect.right + TOOLBAR_SAFE_ZONE + }; + + return mouseX >= safeZone.left && + mouseX <= safeZone.right && + mouseY >= safeZone.top && + mouseY <= safeZone.bottom; + }; + + // Function to handle toolbar hiding with improved logic + window.handleToolbarHiding = (mouseX, mouseY) => { + // Clear any existing timeout + if (toolbarHideTimeout) { + clearTimeout(toolbarHideTimeout); + toolbarHideTimeout = null; + } + + // Don't hide if toolbar is already hidden + if ($('.toolbar').hasClass('toolbar-hidden')) return; + + const wasNearToolbar = isMouseNearToolbar; + isMouseNearToolbar = window.isMouseInToolbarSafeZone(mouseX, mouseY); + + // If mouse is in safe zone, don't hide + if (isMouseNearToolbar) { + return; + } + + // Determine hide delay based on mouse movement pattern + let hideDelay = TOOLBAR_HIDE_DELAY; + + // If mouse was previously near toolbar and now moved far away, hide quicker + if (wasNearToolbar && !isMouseNearToolbar) { + // Check if mouse moved significantly away + const toolbar = $('.toolbar')[0]; + if (toolbar) { + const rect = toolbar.getBoundingClientRect(); + const distanceFromToolbar = Math.min( + Math.abs(mouseY - rect.bottom), + Math.abs(mouseY - rect.top) + ); + + // If mouse is far from toolbar, hide quicker + if (distanceFromToolbar > TOOLBAR_SAFE_ZONE * 2) { + hideDelay = TOOLBAR_QUICK_HIDE_DELAY; + } + } + } + + // Set timeout to hide toolbar + toolbarHideTimeout = setTimeout(() => { + // Double-check mouse position before hiding + if (!window.isMouseInToolbarSafeZone(window.mouseX, window.mouseY)) { + window.hide_toolbar(); + } + toolbarHideTimeout = null; + }, hideDelay); + }; + + // hovering over a hidden toolbar will show it + $(document).on('mouseenter', '.toolbar-hidden', function () { + window.show_toolbar(); + // Clear any pending hide timeout + if (toolbarHideTimeout) { + clearTimeout(toolbarHideTimeout); + toolbarHideTimeout = null; + } + }); + + // hovering over a visible toolbar will show it and cancel hiding + $(document).on('mouseenter', '.toolbar:not(.toolbar-hidden)', function () { + // Clear any pending hide timeout when entering toolbar + if (toolbarHideTimeout) { + clearTimeout(toolbarHideTimeout); + toolbarHideTimeout = null; + } + isMouseNearToolbar = true; + }); + + // Handle mouse leaving the toolbar + $(document).on('mouseleave', '.toolbar', function () { + // if there is not window visible, don't hide the toolbar + if ($('.window-active').length === 0) return; + + // Start the hiding logic with current mouse position + window.handleToolbarHiding(window.mouseX, window.mouseY); + }); + + // Track mouse movement globally to update toolbar hiding logic + $(document).on('mousemove', function(e) { + // if there is not window visible, don't hide the toolbar + if ($('.window-active').length === 0) return; + + // Update global mouse position (assuming this is done elsewhere in the code) + window.mouseX = e.clientX; + window.mouseY = e.clientY; + + // Only handle toolbar hiding if toolbar is visible and mouse moved significantly + if (!$('.toolbar').hasClass('toolbar-hidden')) { + // Use throttling to avoid excessive calls + if (!window.mouseMoveThrottle) { + window.mouseMoveThrottle = setTimeout(() => { + window.handleToolbarHiding(window.mouseX, window.mouseY); + window.mouseMoveThrottle = null; + }, 100); // Throttle to every 100ms + } + } + }); } $(document).on('contextmenu taphold', '.taskbar', function (event) { diff --git a/src/gui/src/UI/UIWindow.js b/src/gui/src/UI/UIWindow.js index 3119e4eef..e7495e0eb 100644 --- a/src/gui/src/UI/UIWindow.js +++ b/src/gui/src/UI/UIWindow.js @@ -3305,6 +3305,9 @@ window.scale_window = (el_window)=>{ 'height': height, 'transform': 'none', }); + + // hide toolbar + window.hide_toolbar(); } //shrink else { diff --git a/src/gui/src/css/style.css b/src/gui/src/css/style.css index b4649c59e..b38892635 100644 --- a/src/gui/src/css/style.css +++ b/src/gui/src/css/style.css @@ -1348,6 +1348,10 @@ span.header-sort-icon img { height: calc(100%); } +.fullpage-mode.device-desktop .window-body-app { + height: calc(100% ); +} + .window-filedialog-prompt { height: 60px; border-top: 1px solid #dbdee3; @@ -1742,9 +1746,11 @@ label { font-size: 14px; } +/*********************************** + * Toolbar + ***********************************/ + .toolbar { - float: right; - width: 100%; background-color: #00000040; height: 30px; position: relative; @@ -1755,7 +1761,18 @@ label { justify-content: flex-end; align-content: center; flex-wrap: wrap; - padding-right: 10px + padding-right: 10px; + left: 50%; + right: 50%; + left: 50%; + transform: translate(-50%); + top: 0px; + border-top-right-radius: 0px; + border-top-left-radius: 0px; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + width: fit-content; + overflow: clip; } .show-desktop-btn { @@ -1807,7 +1824,7 @@ label { } .toolbar-btn:hover { - opacity: 1; + opacity: 1 !important; } .user-options-menu-btn.has-open-contextmenu { @@ -1837,21 +1854,7 @@ label { background-color: rgb(255 255 255 / 15%); border-radius: 3px; } - -.logout-btn { - position: absolute; - right: 7px; - top: 7px; - padding: 4px; - border-radius: 4px; - cursor: pointer; - border: 2px solid #CCC; -} - -.logout-btn img { - width: 20px; - margin-bottom: -5px; -} +/***************************************************/ .login-error-msg, .signup-error-msg, .publish-website-error-msg, .form-error-msg { display: none; diff --git a/src/gui/src/globals.js b/src/gui/src/globals.js index 0129432a1..9a136a791 100644 --- a/src/gui/src/globals.js +++ b/src/gui/src/globals.js @@ -103,7 +103,7 @@ if (window.user_preferences === null) { } window.window_stack = [] -window.toolbar_height = 30; +window.toolbar_height = 0; window.default_taskbar_height = 50; window.taskbar_height = window.default_taskbar_height; window.upload_progress_hide_delay = 500; diff --git a/src/gui/src/initgui.js b/src/gui/src/initgui.js index dea490278..bff79f32d 100644 --- a/src/gui/src/initgui.js +++ b/src/gui/src/initgui.js @@ -1409,6 +1409,11 @@ $(document).on('click', function(e){ if(!$(e.target).hasClass('window-search') && $(e.target).closest('.window-search').length === 0 && !$(e.target).is('.toolbar-btn.search-btn')){ $('.window-search').close(); } + + // any click that is not on .toolbar will hide the toolbar + if(!$(e.target).hasClass('toolbar')){ + window.hide_toolbar(); + } }) // Re-calculate desktop height and width on window resize and re-position the login and signup windows