/**
* 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