/** * Copyright (C) 2024 Puter Technologies Inc. * * This file is part of Puter. * * Puter is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import UIContextMenu from './UIContextMenu.js'; let tray_item_id = 1; function UITaskbarItem(options){ let h = ``; tray_item_id++; options.sortable = options.sortable ?? true; options.open_windows_count = options.open_windows_count ?? 0; options.lock_keep_in_taskbar = options.lock_keep_in_taskbar ?? false; options.append_to_taskbar = options.append_to_taskbar ?? true; const element_id = global_element_id++; h += `
`; let icon = options.icon ? options.icon : window.icons['app.svg']; if(options.app === 'explorer') icon = window.icons['folders.svg']; // taskbar icon h += `
`; h += ``; h += `
`; // active indicator if(options.app !== 'apps') h += ``; h += `
`; if(options.append_to_taskbar) $('.taskbar').append(h); else $('body').prepend(h); const el_taskbar_item = document.querySelector(`#taskbar-item-${tray_item_id}`); // fade in the taskbar item $(el_taskbar_item).show(50); $(el_taskbar_item).on("click", function(){ // If this item has an open context menu, don't do anything if($(el_taskbar_item).hasClass('has-open-contextmenu')) return; if(options.onClick === undefined || options.onClick(el_taskbar_item) === false){ // re-show each window in this app group $(`.window[data-app="${options.app}"]`).showWindow(); } }) $(el_taskbar_item).on('contextmenu taphold', function(e){ // seems like the only way to stop sortable is to destroy it if(options.sortable) { $('.taskbar').sortable('destroy'); } e.preventDefault(); e.stopPropagation(); // If context menu is disabled on this item, return if(options.disable_context_menu) return; // don't allow context menu to open if it's already open if($(el_taskbar_item).hasClass('has-open-contextmenu')) return; const menu_items =[]; const open_windows = parseInt($(el_taskbar_item).attr('data-open-windows')); // ------------------------------------------- // List of open windows belonging to this app // ------------------------------------------- $(`.window[data-app="${options.app}"]`).each(function(){ menu_items.push({ html: $(this).find(`.window-head-title`).html(), val: $(this).attr('data-id'), onClick: function(e){ $(`.window[data-id="${e.value}"]`).showWindow(); } }) }) // ------------------------------------------- // divider // ------------------------------------------- if(menu_items.length > 0) menu_items.push('-'); //------------------------------------------ // New Window //------------------------------------------ if(options.app){ menu_items.push({ html: 'New Window', val: $(this).attr('data-id'), onClick: function(){ launch_app({ name: options.app, maximized: (isMobile.phone || isMobile.tablet), }) } }) } //------------------------------------------ // Empty Trash //------------------------------------------ if(options.app === 'trash' && options.name === 'Trash'){ // divider menu_items.push('-'); // Empty Trash menu item menu_items.push({ html: i18n('empty_trash'), val: $(this).attr('data-id'), onClick: async function(){ empty_trash(); } }) } //------------------------------------------ // Remove from Taskbar //------------------------------------------ if(options.keep_in_taskbar && !options.lock_keep_in_taskbar){ menu_items.push({ html: i18n('remove_from_taskbar'), val: $(this).attr('data-id'), onClick: function(){ $(el_taskbar_item).attr('data-keep-in-taskbar', 'false'); if($(el_taskbar_item).attr('data-open-windows') === '0'){ remove_taskbar_item(el_taskbar_item); } update_taskbar(); options.keep_in_taskbar = false; } }) } //------------------------------------------ // Keep in Taskbar //------------------------------------------ else if(!options.keep_in_taskbar){ menu_items.push({ html: i18n('keep_in_taskbar'), val: $(this).attr('data-id'), onClick: function(){ $(el_taskbar_item).attr('data-keep-in-taskbar', 'true'); update_taskbar(); options.keep_in_taskbar = true; } }) } if(open_windows > 0){ // ------------------------------------------- // divider // ------------------------------------------- menu_items.push('-'); // ------------------------------------------- // Show All Windows // ------------------------------------------- menu_items.push({ html: i18n('show_all_windows'), onClick: function(){ if(open_windows > 0) $(el_taskbar_item).trigger('click'); } }) // ------------------------------------------- // Hide All Windows // ------------------------------------------- menu_items.push({ html: i18n('hide_all_windows'), onClick: function(){ if(open_windows > 0) $(`.window[data-app="${options.app}"]`).hideWindow(); } }) // ------------------------------------------- // Close All Windows // ------------------------------------------- menu_items.push({ html: i18n('close_all_windows'), onClick: function(){ $(`.window[data-app="${options.app}"]`).close(); } }) } const pos = el_taskbar_item.getBoundingClientRect(); UIContextMenu({ parent_element: el_taskbar_item, position: {top: pos.top - 15, left: pos.left+5}, items: menu_items }); return false; }); $( el_taskbar_item ).tooltip({ items: ".taskbar:not(.children-have-open-contextmenu) .taskbar-item", position: { my: "center bottom-20", at: "center top", using: function( position, feedback ) { $( this ).css( position ); $( "
" ) .addClass( "arrow" ) .addClass( feedback.vertical ) .addClass( feedback.horizontal ) .appendTo( this ); } } }); // -------------------------------------------------------- // Droppable // -------------------------------------------------------- $(el_taskbar_item).droppable({ accept: '.item', // 'pointer' is very important because of active window tracking is based on the position of cursor. tolerance: 'pointer', drop: async function( event, ui ) { // Check if hovering over an item that is VISIBILE if($(event.target).closest('.window').attr('data-id') !== $(mouseover_window).attr('data-id')) return; // If ctrl is pressed and source is Trashed, cancel whole operation if(event.ctrlKey && path.dirname($(ui.draggable).attr('data-path')) === window.trash_path) return; const items_to_move = [] // First item items_to_move.push(ui.draggable); // All subsequent items const cloned_items = document.getElementsByClassName('item-selected-clone'); for(let i =0; i 0 && $event_parent_win.attr('data-id') !== $(mouseover_window).attr('data-id')) return; // Don't do anything if the dragged item is NOT a UIItem if(!$(ui.draggable).hasClass('item')) return; // If this is a directory or an app, and an item was dragged over it, highlight it. if(options.is_dir || options.app){ $(el_taskbar_item).addClass('active'); // show tooltip of this item $(el_taskbar_item).tooltip().mouseover(); // make item name partially transparent $('.ui-draggable-dragging .item-name, .item-selected-clone .item-name').css('opacity', 0.1) // remove all item-container active borders $('.item-container').addClass('item-container-transparent-border') } // Disable all window bodies $('.item-container').droppable( 'disable' ) }, out: function(event, ui){ // Don't do anything if the dragged item is NOT a UIItem if(!$(ui.draggable).hasClass('item')) return; // Unselect directory/app if item is dragged out if(options.is_dir || options.app){ $(el_taskbar_item).removeClass('active'); $(el_taskbar_item).tooltip('close'); $('.ui-draggable-dragging .item-name, .item-selected-clone .item-name').css('opacity', 'initial') $('.item-container').removeClass('item-container-transparent-border') } $('.item-container').droppable( 'enable' ) } }); return el_taskbar_item; } export default UITaskbarItem