Configurable taskbar position (#1372)

* feat(gui): Enhance taskbar functionality and positioning

- Implement dynamic taskbar position management with options for left, bottom, and right placements.
- Update desktop dimensions and window positioning based on taskbar position.
- Add context menu options for changing taskbar position on desktop devices.
- Ensure mobile devices always display the taskbar at the bottom.
- Introduce CSS styles for taskbar positioning and adjust desktop padding accordingly.

* feat(gui): Reinitialize tooltips based on taskbar position

- Implement dynamic tooltip positioning for taskbar items based on the current taskbar location (left, right, bottom).
- Ensure tooltips are destroyed and recreated when the taskbar position is updated, enhancing user experience and consistency.

* feat(gui): Improve taskbar and tooltip positioning

- Add support for dynamic tooltip positioning for the 'top' taskbar location.
- Adjust CSS styles for arrow tooltips to enhance visual alignment and positioning.
- Refine taskbar item positioning for left and right placements to ensure consistent appearance.

* Improve popover positioning based on taskbar location

- Improve `UIPopover` positioning logic to account for left and right taskbar placements.
- Adjust Y position of popovers to ensure they appear correctly below toolbars for left/right taskbars.
- Update CSS styles for arrow tooltips to enforce consistent positioning with !important declarations.

* Refactor context menu positioning logic in UITaskbarItem

- Introduce a helper function to dynamically calculate context menu position based on the taskbar's location (top, bottom, left, right).
- Ensure context menus are positioned correctly relative to the taskbar item, improving usability across different taskbar placements.

* Fix UITaskbar window height calculation for consistent positioning

- Adjust the height calculation for windows in the UITaskbar to remove an unnecessary offset, ensuring accurate window sizing relative to the toolbar height.
- This change improves the visual consistency of maximized windows across different taskbar placements.

* Enhance window snapping and positioning based on taskbar location

- Introduce a new function to calculate snap dimensions and positions dynamically based on the taskbar's location (left, right, bottom).
- Update window snapping logic to ensure windows are positioned correctly relative to the taskbar, improving usability and visual consistency.
- Adjust boundary checks for window placement to account for taskbar height and position, enhancing the overall user experience.

* Update default taskbar position to 'left' and adjust CSS padding for desktop layout

- Change the default taskbar position from 'bottom' to 'left' in UITaskbar.
- Modify CSS to increase left padding for desktop taskbar positioning, enhancing layout consistency.

* Improve CSS for desktop layout with height adjustments

- Update CSS styles for input fields and desktop taskbar to set height to 100vh, ensuring consistent full-page layout across different screen sizes.
- This change improves the visual consistency and usability of the interface.

* Improve desktop selectable interactivity and taskbar tooltip behavior

- Add functionality to mark the desktop as selectable active, improving user interaction with desktop elements.
- Update tooltip display logic to only show when the desktop is not in a selectable state, enhancing usability.
- Adjust CSS styles for desktop layout, ensuring consistent behavior and appearance when the desktop is active or inactive.

* Update default taskbar position logic for first-time and existing users

- Set the taskbar position to 'left' for first-time visitors and default to 'bottom' for returning users without a saved preference.
- This change improves the user experience by providing a more intuitive initial layout for new users while maintaining consistency for existing users.
This commit is contained in:
Nariman Jelveh
2025-07-23 15:48:23 -07:00
committed by GitHub
parent 5b46f0bcb1
commit bfd1f8faab
6 changed files with 702 additions and 143 deletions

View File

@@ -748,6 +748,9 @@ async function UIDesktop(options) {
// ---------------------------------------------------------------
UITaskbar();
// Update desktop dimensions after taskbar is initialized with position
window.update_desktop_dimensions_for_taskbar();
const el_desktop = document.querySelector('.desktop');
window.active_element = el_desktop;
@@ -1100,6 +1103,9 @@ async function UIDesktop(options) {
selection.clearSelection();
}
// mark desktop as selectable active
$('.desktop').addClass('desktop-selectable-active');
})
.on('move', ({ store: { changed: { added, removed } }, event }) => {
window.desktop_selectable_is_active = true;
@@ -1125,6 +1131,7 @@ async function UIDesktop(options) {
})
.on('stop', evt => {
window.desktop_selectable_is_active = false;
$('.desktop').removeClass('desktop-selectable-active');
});
}
// ----------------------------------------------------
@@ -1755,31 +1762,66 @@ $(document).on('contextmenu taphold', '.taskbar', function (event) {
event.preventDefault();
event.stopPropagation();
// Get current taskbar position
const currentPosition = window.taskbar_position || 'bottom';
// Create base menu items
let menuItems = [];
// Only show position submenu on desktop devices
if (!isMobile.phone && !isMobile.tablet) {
menuItems.push({
html: "Position",
items: [
{
html: "Left",
checked: currentPosition === 'left',
onClick: function() {
window.update_taskbar_position('left');
}
},
{
html: "Bottom",
checked: currentPosition === 'bottom',
onClick: function() {
window.update_taskbar_position('bottom');
}
},
{
html: "Right",
checked: currentPosition === 'right',
onClick: function() {
window.update_taskbar_position('right');
}
}
]
});
menuItems.push('-'); // divider
}
// Add the "Show open windows" option for all devices
menuItems.push({
html: "Show open windows",
onClick: function () {
$(`.window`).showWindow();
}
});
// Add the "Show the desktop" option for all devices
menuItems.push({
html: "Show the desktop",
onClick: function () {
$(`.window`).hideWindow();
}
});
UIContextMenu({
parent_element: $('.taskbar'),
items: [
//--------------------------------------------------
// Show open windows
//--------------------------------------------------
{
html: "Show open windows",
onClick: function () {
$(`.window`).showWindow();
}
},
//--------------------------------------------------
// Show the desktop
//--------------------------------------------------
{
html: "Show the desktop",
onClick: function () {
$(`.window`).hideWindow();
}
}
]
items: menuItems
});
return false;
})
});
// Toolbar context menu
$(document).on('contextmenu taphold', '.toolbar', function (event) {

View File

@@ -62,7 +62,19 @@ function UIPopover(options){
// X position
const popover_width = options.width ?? $(el_popover).width();
if(options.center_horizontally){
x_pos = window.innerWidth/2 - popover_width/2 - 15;
// Check taskbar position to determine popover positioning
const taskbar_position = window.taskbar_position || 'bottom';
if(taskbar_position === 'left'){
// Position in top-left corner for left taskbar
x_pos = window.taskbar_height + 10; // Just to the right of the taskbar
}else if(taskbar_position === 'right'){
// Position in top-right corner for right taskbar
x_pos = window.innerWidth - popover_width - window.taskbar_height - 40; // Just to the left of the taskbar
}else{
// Default bottom taskbar behavior - center horizontally
x_pos = window.innerWidth/2 - popover_width/2 - 15;
}
}else{
if(options.position === 'bottom' || options.position === 'top')
x_pos = options.left ?? ($(options.snapToElement).offset().left - (popover_width/ 2) + 10);
@@ -73,7 +85,16 @@ function UIPopover(options){
// Y position
const popover_height = options.height ?? $(el_popover).height();
if(options.center_horizontally){
y_pos = options.top ?? (window.innerHeight - (window.taskbar_height + popover_height + 10));
// Check taskbar position to determine popover positioning
const taskbar_position = window.taskbar_position || 'bottom';
if(taskbar_position === 'left' || taskbar_position === 'right'){
// Position at top for left/right taskbars
y_pos = window.toolbar_height + 10; // Just below the toolbar
}else{
// Default bottom taskbar behavior - position above taskbar
y_pos = options.top ?? (window.innerHeight - (window.taskbar_height + popover_height + 10));
}
}else{
y_pos = options.top ?? ($(options.snapToElement).offset().top + $(options.snapToElement).height() + 5);
}

View File

@@ -27,6 +27,30 @@ async function UITaskbar(options){
options = options ?? {};
options.content = options.content ?? '';
// if first visit ever, set taskbar position to left
if(window.first_visit_ever){
await puter.kv.set('taskbar_position', 'left');
}
// Load taskbar position preference from storage
let taskbar_position = await puter.kv.get('taskbar_position');
// if this is not first visit, set taskbar position to bottom since it's from a user that
// used puter before customizing taskbar position was added and the taskbar position was set to bottom
if (!taskbar_position) {
taskbar_position = 'bottom'; // default position
await puter.kv.set('taskbar_position', taskbar_position);
}
// Force bottom position on mobile devices
if (isMobile.phone || isMobile.tablet) {
taskbar_position = 'bottom';
// Update the stored preference to bottom for mobile devices
await puter.kv.set('taskbar_position', taskbar_position);
}
// Set global taskbar position
window.taskbar_position = taskbar_position;
// get launch apps
$.ajax({
url: window.api_origin + "/get-launch-apps?icon_size=64",
@@ -42,10 +66,13 @@ async function UITaskbar(options){
});
let h = '';
h += `<div id="ui-taskbar_${window.global_element_id}" class="taskbar" style="height:${window.taskbar_height}px;">`;
h += `<div id="ui-taskbar_${window.global_element_id}" class="taskbar taskbar-position-${taskbar_position}" style="height:${window.taskbar_height}px;">`;
h += `<div class="taskbar-sortable" style="display: flex; justify-content: center; z-index: 99999;"></div>`;
h += `</div>`;
if(taskbar_position === 'left' || taskbar_position === 'right'){
$('.desktop').addClass(`desktop-taskbar-position-${taskbar_position}`);
}
$('.desktop').append(h);
@@ -242,12 +269,15 @@ async function UITaskbar(options){
window.make_taskbar_sortable();
}
//-------------------------------------------
// Taskbar is sortable
//-------------------------------------------
window.make_taskbar_sortable = function(){
//-------------------------------------------
// Taskbar is sortable
//-------------------------------------------
const position = window.taskbar_position || 'bottom';
const axis = position === 'bottom' ? 'x' : 'y';
$('.taskbar-sortable').sortable({
axis: "x",
axis: axis,
items: '.taskbar-item-sortable:not(.has-open-contextmenu)',
cancel: '.has-open-contextmenu',
placeholder: "taskbar-item-sortable-placeholder",
@@ -304,4 +334,171 @@ window.make_taskbar_sortable = function(){
});
}
// Function to update taskbar position
window.update_taskbar_position = async function(new_position) {
// Prevent position changes on mobile devices - always keep bottom
if (isMobile.phone || isMobile.tablet) {
return;
}
// Valid positions
const valid_positions = ['left', 'bottom', 'right'];
if (!valid_positions.includes(new_position)) {
return;
}
// Store the new position
await puter.kv.set('taskbar_position', new_position);
window.taskbar_position = new_position;
// Remove old position classes and add new one
$('.taskbar').removeClass('taskbar-position-left taskbar-position-bottom taskbar-position-right');
$('.taskbar').addClass(`taskbar-position-${new_position}`);
// update desktop class, if left or right, add `desktop-taskbar-position-left` or `desktop-taskbar-position-right`
$('.desktop').removeClass('desktop-taskbar-position-left');
$('.desktop').removeClass('desktop-taskbar-position-right');
$('.desktop').addClass(`desktop-taskbar-position-${new_position}`);
// Update desktop height/width calculations based on new position
window.update_desktop_dimensions_for_taskbar();
// Update window positions if needed (for maximized windows)
$('.window[data-is_maximized="1"]').each(function() {
const el_window = this;
window.update_maximized_window_for_taskbar(el_window);
});
// Re-initialize sortable with correct axis
$('.taskbar-sortable').sortable('destroy');
window.make_taskbar_sortable();
// Reinitialize all taskbar item tooltips with new position
$('.taskbar-item').each(function() {
const $item = $(this);
// Destroy existing tooltip
if ($item.data('ui-tooltip')) {
$item.tooltip('destroy');
}
// Helper function to get tooltip position based on taskbar position
function getTooltipPosition() {
const taskbarPosition = window.taskbar_position || 'bottom';
if (taskbarPosition === 'bottom') {
return {
my: "center bottom-20",
at: "center top"
};
} else if (taskbarPosition === 'top') {
return {
my: "center top+20",
at: "center bottom"
};
} else if (taskbarPosition === 'left') {
return {
my: "left+20 center",
at: "right center"
};
} else if (taskbarPosition === 'right') {
return {
my: "right-20 center",
at: "left center"
};
}
return {
my: "center bottom-20",
at: "center top"
}; // fallback
}
const tooltipPosition = getTooltipPosition();
// Reinitialize tooltip with new position
$item.tooltip({
items: ".taskbar:not(.children-have-open-contextmenu) .taskbar-item",
position: {
my: tooltipPosition.my,
at: tooltipPosition.at,
using: function( position, feedback ) {
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
});
});
};
// Function to update desktop dimensions based on taskbar position
window.update_desktop_dimensions_for_taskbar = function() {
const position = window.taskbar_position || 'bottom';
if (position === 'bottom') {
$('.desktop').css({
'height': `calc(100vh - ${window.taskbar_height + window.toolbar_height}px)`,
'width': '100%',
'left': '0',
'top': `${window.toolbar_height}px`
});
} else if (position === 'left') {
$('.desktop').css({
'height': `calc(100vh - ${window.toolbar_height}px)`,
'width': `calc(100% - ${window.taskbar_height}px)`,
'left': `${window.taskbar_height}px`,
'top': `${window.toolbar_height}px`
});
} else if (position === 'right') {
$('.desktop').css({
'height': `calc(100vh - ${window.toolbar_height}px)`,
'width': `calc(100% - ${window.taskbar_height}px)`,
'left': '0',
'top': `${window.toolbar_height}px`
});
}
};
// Function to update maximized window positioning based on taskbar position
window.update_maximized_window_for_taskbar = function(el_window) {
const position = window.taskbar_position || 'bottom';
// Handle fullpage mode differently
if (window.is_fullpage_mode) {
$(el_window).css({
'top': window.toolbar_height + 'px',
'left': '0',
'width': '100%',
'height': `calc(100% - ${window.toolbar_height}px)`,
});
return;
}
if (position === 'bottom') {
$(el_window).css({
'top': window.toolbar_height + 'px',
'left': '0',
'width': '100%',
'height': `calc(100% - ${window.taskbar_height + window.toolbar_height + 6}px)`,
});
} else if (position === 'left') {
$(el_window).css({
'top': window.toolbar_height + 'px',
'left': window.taskbar_height + 'px',
'width': `calc(100% - ${window.taskbar_height}px)`,
'height': `calc(100% - ${window.toolbar_height}px)`,
});
} else if (position === 'right') {
$(el_window).css({
'top': window.toolbar_height + 'px',
'left': '0',
'width': `calc(100% - ${window.taskbar_height}px)`,
'height': `calc(100% - ${window.toolbar_height}px)`,
});
}
};
export default UITaskbar;

View File

@@ -268,27 +268,92 @@ function UITaskbarItem(options){
const pos = el_taskbar_item.getBoundingClientRect();
UIContextMenu({
parent_element: el_taskbar_item,
position: {top: pos.top - 15, left: pos.left+5},
position: getContextMenuPosition(pos),
items: menu_items
});
return false;
});
$( el_taskbar_item ).tooltip({
items: ".taskbar:not(.children-have-open-contextmenu) .taskbar-item",
position: {
// Helper function to get tooltip position based on taskbar position
function getTooltipPosition() {
const taskbarPosition = window.taskbar_position || 'bottom';
if (taskbarPosition === 'bottom') {
return {
my: "center bottom-20",
at: "center top"
};
} else if (taskbarPosition === 'top') {
return {
my: "center top+20",
at: "center bottom"
};
} else if (taskbarPosition === 'left') {
return {
my: "left+20 center",
at: "right center"
};
} else if (taskbarPosition === 'right') {
return {
my: "right-20 center",
at: "left center"
};
}
return {
my: "center bottom-20",
at: "center top",
at: "center top"
}; // fallback
}
// Helper function to get context menu position based on taskbar position
function getContextMenuPosition(pos) {
const taskbarPosition = window.taskbar_position || 'bottom';
if (taskbarPosition === 'bottom') {
return {
top: pos.top - 15,
left: pos.left + 5
};
} else if (taskbarPosition === 'top') {
return {
top: pos.bottom + 15,
left: pos.left + 5
};
} else if (taskbarPosition === 'left') {
return {
top: pos.top + 5,
left: pos.right + 5
};
} else if (taskbarPosition === 'right') {
return {
top: pos.top + 5,
left: pos.left - 20
};
}
return {
top: pos.top - 15,
left: pos.left + 5
}; // fallback
}
const tooltipPosition = getTooltipPosition();
$( el_taskbar_item ).tooltip({
// only show tooltip if desktop is not selectable active
items: ".desktop:not(.desktop-selectable-active) .taskbar:not(.children-have-open-contextmenu) .taskbar-item",
position: {
my: tooltipPosition.my,
at: tooltipPosition.at,
using: function( position, feedback ) {
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
},
});
// --------------------------------------------------------

View File

@@ -34,6 +34,37 @@ import item_icon from '../helpers/item_icon.js';
const el_body = document.getElementsByTagName('body')[0];
// Function to get snap dimensions and positions based on taskbar position
function getSnapDimensions() {
const taskbar_position = window.taskbar_position || 'bottom';
let available_width, available_height, start_x, start_y;
if (taskbar_position === 'left') {
available_width = window.innerWidth - window.taskbar_height;
available_height = window.innerHeight - window.toolbar_height;
start_x = window.taskbar_height;
start_y = window.toolbar_height;
} else if (taskbar_position === 'right') {
available_width = window.innerWidth - window.taskbar_height;
available_height = window.innerHeight - window.toolbar_height;
start_x = 0;
start_y = window.toolbar_height;
} else { // bottom (default)
available_width = window.innerWidth;
available_height = window.innerHeight - window.toolbar_height - window.taskbar_height;
start_x = 0;
start_y = window.toolbar_height;
}
return {
available_width,
available_height,
start_x,
start_y
};
}
async function UIWindow(options) {
const win_id = window.global_element_id++;
window.last_window_zindex++;
@@ -549,14 +580,8 @@ async function UIWindow(options) {
// shrink icon
$(el_window).find('.window-scale-btn>img').attr('src', window.icons['scale-down-3.svg']);
// set new size and position
$(el_window).css({
'top': window.toolbar_height + 'px',
'left': '0',
'width': '100%',
'height': `calc(100% - ${window.taskbar_height + window.toolbar_height + 6}px)`,
'transform': 'none',
});
// Use taskbar position-aware window positioning
window.update_maximized_window_for_taskbar(el_window);
}
// when a window is created, focus is brought to it and
@@ -1701,14 +1726,17 @@ async function UIWindow(options) {
return;
}
// Get taskbar-aware snap dimensions
const snapDims = getSnapDimensions();
// W
if(!window_is_snapped && window.current_active_snap_zone === 'w'){
window_snap_placeholder.css({
'display': 'block',
'width': '50%',
'height': window.desktop_height,
'top': window.toolbar_height,
'left': 0,
'width': snapDims.available_width / 2,
'height': snapDims.available_height,
'top': snapDims.start_y,
'left': snapDims.start_x,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1716,10 +1744,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone === 'nw'){
window_snap_placeholder.css({
'display': 'block',
'width': '50%',
'height': window.desktop_height/2,
'top': window.toolbar_height,
'left': 0,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
'top': snapDims.start_y,
'left': snapDims.start_x,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1727,10 +1755,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone ==='ne'){
window_snap_placeholder.css({
'display': 'block',
'width': '50%',
'height': window.desktop_height/2,
'top': window.toolbar_height,
'left': window.desktop_width/2,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
'top': snapDims.start_y,
'left': snapDims.start_x + snapDims.available_width / 2,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1738,11 +1766,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone ==='e'){
window_snap_placeholder.css({
'display': 'block',
'width': '50%',
'height': window.desktop_height,
'top': window.toolbar_height,
'left': 'initial',
'right': 0,
'width': snapDims.available_width / 2,
'height': snapDims.available_height,
'top': snapDims.start_y,
'left': snapDims.start_x + snapDims.available_width / 2,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1750,10 +1777,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone ==='n'){
window_snap_placeholder.css({
'display': 'block',
'width': window.desktop_width,
'height': window.desktop_height,
'top': window.toolbar_height,
'left': 0,
'width': snapDims.available_width,
'height': snapDims.available_height,
'top': snapDims.start_y,
'left': snapDims.start_x,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1761,10 +1788,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone ==='sw'){
window_snap_placeholder.css({
'display': 'block',
'top': window.toolbar_height + window.desktop_height/2,
'left': 0,
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y + snapDims.available_height / 2,
'left': snapDims.start_x,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1772,10 +1799,10 @@ async function UIWindow(options) {
else if(!window_is_snapped && window.current_active_snap_zone ==='se'){
window_snap_placeholder.css({
'display': 'block',
'top': window.toolbar_height + window.desktop_height/2,
'left': window.desktop_width/2,
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y + snapDims.available_height / 2,
'left': snapDims.start_x + snapDims.available_width / 2,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
'z-index': window.last_window_zindex - 1,
})
}
@@ -1823,58 +1850,61 @@ async function UIWindow(options) {
$(window_snap_placeholder).css('padding', 0);
setTimeout(function(){
// Get taskbar-aware snap dimensions for final positioning
const snapDims = getSnapDimensions();
// snap to w
if(window.current_active_snap_zone === 'w'){
$(el_window).css({
'top': window.toolbar_height,
'left': 0,
'width': '50%',
'height': window.desktop_height - 6,
'top': snapDims.start_y,
'left': snapDims.start_x,
'width': snapDims.available_width / 2,
'height': snapDims.available_height - 6,
})
}
// snap to nw
else if(window.current_active_snap_zone === 'nw'){
$(el_window).css({
'top': window.toolbar_height,
'left': 0,
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y,
'left': snapDims.start_x,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
})
}
// snap to ne
else if(window.current_active_snap_zone === 'ne'){
$(el_window).css({
'top': window.toolbar_height,
'left': '50%',
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y,
'left': snapDims.start_x + snapDims.available_width / 2,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
})
}
// snap to sw
else if(window.current_active_snap_zone === 'sw'){
$(el_window).css({
'top': window.toolbar_height + window.desktop_height/2,
'left': 0,
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y + snapDims.available_height / 2,
'left': snapDims.start_x,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
})
}
// snap to se
else if(window.current_active_snap_zone === 'se'){
$(el_window).css({
'top': window.toolbar_height + window.desktop_height/2,
'left': window.desktop_width/2,
'width': '50%',
'height': window.desktop_height/2,
'top': snapDims.start_y + snapDims.available_height / 2,
'left': snapDims.start_x + snapDims.available_width / 2,
'width': snapDims.available_width / 2,
'height': snapDims.available_height / 2,
})
}
// snap to e
else if(window.current_active_snap_zone === 'e'){
$(el_window).css({
'top': window.toolbar_height,
'left': '50%',
'width': '50%',
'height': window.desktop_height - 6,
'top': snapDims.start_y,
'left': snapDims.start_x + snapDims.available_width / 2,
'width': snapDims.available_width / 2,
'height': snapDims.available_height - 6,
})
}
// snap to n
@@ -1906,23 +1936,43 @@ async function UIWindow(options) {
}, 100);
}
// if window is dropped below the taskbar, move it up
// if window is dropped outside the available area, move it back in
// Bottom boundary (account for taskbar position)
const taskbar_position = window.taskbar_position || 'bottom';
let maxTop;
if(taskbar_position === 'bottom'){
maxTop = window.innerHeight - window.taskbar_height - 30;
} else {
maxTop = window.innerHeight - 30;
}
// the lst '- 30' is to account for the window head
if($(el_window).position().top > window.innerHeight - window.taskbar_height - 30 && !window_will_snap){
if($(el_window).position().top > maxTop && !window_will_snap){
$(el_window).animate({
top: window.innerHeight - window.taskbar_height - 60,
top: maxTop - 30,
}, 100);
}
// if window is dropped too far to the right, move it left
if($(el_window).position().left > window.innerWidth - 50 && !window_will_snap){
let maxLeft;
if(taskbar_position === 'right'){
maxLeft = window.innerWidth - window.taskbar_height - 50;
} else {
maxLeft = window.innerWidth - 50;
}
if($(el_window).position().left > maxLeft && !window_will_snap){
$(el_window).animate({
left: window.innerWidth - 50,
left: maxLeft,
}, 100);
}
// if window is dropped too far to the left, move it right
if(($(el_window).position().left + $(el_window).width() - 150 )< 0 && !window_will_snap){
let minLeft;
if(taskbar_position === 'left'){
minLeft = window.taskbar_height - $(el_window).width() + 150;
} else {
minLeft = -$(el_window).width() + 150;
}
if($(el_window).position().left < minLeft && !window_will_snap){
$(el_window).animate({
left: -1 * ($(el_window).width() - 150),
left: minLeft,
}, 100);
}
},
@@ -3296,22 +3346,8 @@ window.scale_window = (el_window)=>{
// shrink icon
$(el_window).find('.window-scale-btn>img').attr('src', window.icons['scale-down-3.svg']);
// calculate height
let height;
if(window.is_fullpage_mode){
height = `calc(100% - ${ window.toolbar_height}px)`;
}else{
height = `calc(100% - ${window.taskbar_height + window.toolbar_height + 6}px)`;
}
// set new size and position
$(el_window).css({
'top': window.toolbar_height+'px',
'left': '0',
'width': '100%',
'height': height,
'transform': 'none',
});
// Use taskbar position-aware window positioning
window.update_maximized_window_for_taskbar(el_window);
// hide toolbar
if(!isMobile.phone && !isMobile.tablet){
@@ -3562,9 +3598,29 @@ $.fn.hideWindow = async function(options) {
if($(this).hasClass('window')){
// get taskbar item location
let taskbar_item_pos = $(`.taskbar .taskbar-item[data-app="${$(this).attr('data-app')}"]`).position();
// taskbar position is center of window minus half of taskbar item width
taskbar_item_pos.left = taskbar_item_pos.left + ($( window ).width()/ 2) - ($(`.taskbar`).width() / 2);
// Calculate animation target based on taskbar position
let animationTarget = {};
const taskbarPosition = window.taskbar_position || 'bottom';
if (taskbarPosition === 'bottom') {
// taskbar position is center of window minus half of taskbar item width
taskbar_item_pos.left = taskbar_item_pos.left + ($( window ).width()/ 2) - ($(`.taskbar`).width() / 2);
animationTarget = {
top: 'calc(100% - 60px)',
left: taskbar_item_pos.left + 14.5,
};
} else if (taskbarPosition === 'left') {
animationTarget = {
top: taskbar_item_pos.top + ($( window ).height()/ 2) - ($(`.taskbar`).height() / 2) + 14.5,
left: '5px',
};
} else if (taskbarPosition === 'right') {
animationTarget = {
top: taskbar_item_pos.top + ($( window ).height()/ 2) - ($(`.taskbar`).height() / 2) + 14.5,
left: 'calc(100% - 60px)',
};
}
$(this).attr({
'data-orig-width': $(this).width(),
@@ -3580,8 +3636,7 @@ $.fn.hideWindow = async function(options) {
} : {}),
width: `0`,
height: `0`,
top: 'calc(100% - 60px)',
left: taskbar_item_pos.left + 14.5,
...animationTarget,
});
// remove transitions a good while after setting css to make sure

View File

@@ -340,7 +340,7 @@ input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, sel
.desktop {
display: none;
overflow: hidden;
height: calc(100vh - 60px);
height: calc(100vh - 60px) !important;
width: 100%;
display: grid;
grid-template-rows: repeat(auto-fill, 109px);
@@ -349,6 +349,24 @@ input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, sel
padding-top: 15px;
}
.device-desktop .desktop {
padding-top: 5px;
}
.desktop.desktop-taskbar-position-left {
margin-left: 50px;
padding-right: 0;
padding-bottom: 0;
height: calc(100vh) !important;
}
.desktop.desktop-taskbar-position-right {
margin-right: 50px;
padding-left: 0;
padding-bottom: 0;
height: calc(100vh) !important;
}
.fullpage-mode .window-minimize-btn {
display: none;
}
@@ -356,6 +374,10 @@ input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, sel
.device-phone .desktop {
height: calc(100vh - 90px) !important;
height: calc(100dvh - 90px) !important;
/* Ensure no left/right padding on mobile, regardless of taskbar position classes */
padding-left: 0 !important;
padding-right: 0 !important;
padding-bottom: 0 !important;
}
.item-container-list {
@@ -2355,6 +2377,74 @@ label {
0 4px 16px rgba(0, 0, 0, 0.2);
}
/* Bottom positioned taskbar (default) */
.taskbar.taskbar-position-bottom {
bottom: 5px;
left: 50%;
right: auto;
top: auto;
width: auto;
height: 50px;
transform: translateX(-50%);
flex-direction: row;
justify-content: center;
writing-mode: initial;
}
/* Left positioned taskbar */
.taskbar.taskbar-position-left {
left: 0;
top: 0;
width: 50px;
transform: none;
height: 100% !important;
flex-direction: column;
justify-content: normal;
writing-mode: initial;
padding-top: 7px;
padding-bottom: 7px;
padding-left: 0;
padding-right: 0;
border-radius: 0;
}
/* Right positioned taskbar */
.taskbar.taskbar-position-right {
right: 0;
top: 0;
left: auto;
bottom: auto;
width: 50px;
height: 100% !important;
transform: none;
flex-direction: column;
justify-content: normal;
writing-mode: initial;
padding-top: 7px;
padding-bottom: 7px;
padding-left: 0;
padding-right: 0;
border-radius: 0;
}
.taskbar.taskbar-position-left .taskbar-sortable,
.taskbar.taskbar-position-right .taskbar-sortable {
display: block !important;
}
/* Taskbar items for left/right positioning */
.taskbar.taskbar-position-left .taskbar-item,
.taskbar.taskbar-position-right .taskbar-item {
margin-bottom: 5px;
margin-left: 0;
margin-right: 0;
}
.taskbar.taskbar-position-left .taskbar-item:last-child,
.taskbar.taskbar-position-right .taskbar-item:last-child {
margin-bottom: 0;
}
.taskbar .taskbar-item {
float: left;
position: relative;
@@ -2386,7 +2476,7 @@ label {
z-index: 999999999 !important;
}
.taskbar .taskbar-item:hover .taskbar-icon {
.desktop:not(.desktop-selectable-active) .taskbar .taskbar-item:hover .taskbar-icon {
background-color: rgb(255 255 255 / 40%);
transition: background-color 0.2s;
}
@@ -2546,6 +2636,7 @@ label {
filter: drop-shadow(0 0 3px rgba(0, 0, 0, .455));
}
/* Base arrow styles */
.arrow {
width: 70px;
height: 16px;
@@ -2557,15 +2648,6 @@ label {
border-top: none;
}
.arrow.top {
top: -16px;
bottom: auto;
}
.arrow.left {
left: 20%;
}
.arrow:after {
content: "";
position: absolute;
@@ -2576,11 +2658,94 @@ label {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
background-color: rgba(231, 238, 245, .92);
}
/* Arrow pointing up (tooltip below taskbar item) */
.arrow.bottom {
bottom: auto;
top: 31px !important;
transform: scaleY(-1);
left: calc(50% + 2px) !important;
}
.arrow.bottom:after {
bottom: -20px;
top: auto;
}
/* Arrow pointing down (tooltip above taskbar item) */
.arrow.top {
top: auto;
bottom: -16px;
}
.arrow.top:after {
bottom: -20px;
top: auto;
top: -20px;
bottom: auto;
}
/* Arrow pointing right (tooltip to the right of taskbar item) */
.arrow.left {
width: 16px;
height: 70px;
left: -16px;
right: auto;
bottom: auto;
margin-left: 0;
margin-top: -37px;
transform: scaleX(-1);
top:18px !important;
}
.arrow.left:after {
left: -20px;
top: 20px;
right: auto;
bottom: auto;
}
/* Arrow pointing left (tooltip to the left of taskbar item) */
.arrow.right {
width: 16px;
height: 70px;
right: -16px !important;
left: auto;
margin-left: 0;
margin-top: 35px;
transform: scaleX(-1);
position: absolute;
top:18px !important;
}
.arrow.right:after {
right: -20px !important;
left: auto !important;
top: 20px;
bottom: auto;
}
/* Center positioning adjustments */
.arrow.center {
left: 50%;
margin-left: -35px;
}
.arrow.middle {
top: 50%;
margin-top: -35px;
}
/* Horizontal center adjustments for left/right arrows */
.arrow.left.middle,
.arrow.right.middle {
margin-top: -35px;
}
/* Vertical center adjustments for top/bottom arrows */
.arrow.top.center,
.arrow.bottom.center {
margin-left: -35px;
}
/******************************************************/
@@ -4599,6 +4764,21 @@ fieldset[name=number-code] {
/* Taskbar container */
.device-phone .taskbar {
/* Force taskbar to bottom on mobile devices, overriding any position classes */
position: fixed !important;
bottom: 5px !important;
left: 50% !important;
right: auto !important;
top: auto !important;
width: auto !important;
height: 50px !important;
transform: translateX(-50%) !important;
flex-direction: row !important;
justify-content: left !important;
writing-mode: initial !important;
padding: 0 7px !important;
border-radius: 10px !important;
/* Enable smooth scrolling */
-webkit-overflow-scrolling: touch;
/* Allow horizontal touch scrolling */
@@ -4611,7 +4791,6 @@ fieldset[name=number-code] {
/* Base styling */
display: flex;
justify-content: left;
}
/* Hide scrollbar while keeping functionality */