mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-27 11:55:50 +00:00
Remove legacy TabFiles component
Delete the large TabFiles.js file (file browser tab) and update dashboard, styles, helpers, and init logic accordingly. Related changes in UIDashboard.js, dashboard.css, style.css, helpers.js and initgui.js remove or adapt references to the removed component and adjust UI/initialization and styling to account for the file-tab extraction. This reduces duplicate/legacy code and centralizes file browser functionality; review UIDashboard and helper updates to ensure file management features (navigation, upload, context menus, previews) are migrated or re-implemented as needed.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,6 @@ import UIWindowFeedback from '../UIWindowFeedback.js';
|
||||
|
||||
// Import tab modules
|
||||
import TabHome from './TabHome.js';
|
||||
import TabFiles from './TabFiles.js';
|
||||
import TabApps from './TabApps.js';
|
||||
import TabUsage from './TabUsage.js';
|
||||
import TabAccount from './TabAccount.js';
|
||||
@@ -54,7 +53,6 @@ import TabSecurity from './TabSecurity.js';
|
||||
const builtinTabs = [
|
||||
TabHome,
|
||||
TabApps,
|
||||
TabFiles,
|
||||
'-',
|
||||
TabUsage,
|
||||
TabAccount,
|
||||
@@ -156,11 +154,6 @@ async function UIDashboard (options) {
|
||||
$el_window.find('.dashboard-sidebar').addClass('collapsed');
|
||||
}
|
||||
|
||||
// Set initial file path BEFORE tabs are initialized (so TabFiles.init() can use it)
|
||||
if ( window.dashboard_initial_route?.tab === 'files' && window.dashboard_initial_route?.path ) {
|
||||
window.dashboard_initial_file_path = window.dashboard_initial_route.path;
|
||||
}
|
||||
|
||||
// Initialize all tabs
|
||||
for ( const tab of tabs ) {
|
||||
if ( tab.init ) {
|
||||
@@ -232,97 +225,6 @@ async function UIDashboard (options) {
|
||||
}
|
||||
});
|
||||
|
||||
// Trash status updates
|
||||
window.socket.on('trash.is_empty', async (msg) => {
|
||||
// Update sidebar Trash icon
|
||||
const trashIcon = msg.is_empty ? window.icons['trash.svg'] : window.icons['trash-full.svg'];
|
||||
$('.directories [data-folder=\'Trash\'] img').attr('src', trashIcon);
|
||||
|
||||
// If currently viewing trash and it's empty, clear the file list
|
||||
const dashboard = window.dashboard_object;
|
||||
if ( msg.is_empty && dashboard && dashboard.currentPath === window.trash_path ) {
|
||||
$('.files-tab .files').empty();
|
||||
}
|
||||
});
|
||||
|
||||
// =========================================================================
|
||||
// Item event handlers
|
||||
// Incremental DOM updates using UIDashboardFileItem for item creation and
|
||||
// direct jQuery manipulation for removals/updates. Mirrors UIDesktop's
|
||||
// approach but adapted for Dashboard's list-view structure.
|
||||
// =========================================================================
|
||||
|
||||
window.socket.on('item.moved', async (resp) => {
|
||||
if ( resp.original_client_socket_id === window.socket.id ) return;
|
||||
|
||||
// Fade out old item from view
|
||||
$(`.item[data-uid='${resp.uid}']`).fadeOut(150, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
// Create new item at destination if user is viewing that directory
|
||||
if ( window.UIDashboardFileItem ) {
|
||||
window.UIDashboardFileItem(resp);
|
||||
}
|
||||
});
|
||||
|
||||
window.socket.on('item.removed', async (item) => {
|
||||
if ( item.original_client_socket_id === window.socket.id ) return;
|
||||
if ( item.descendants_only ) return;
|
||||
|
||||
$(`.item[data-path='${html_encode(item.path)}']`).fadeOut(150, function () {
|
||||
$(this).remove();
|
||||
});
|
||||
});
|
||||
|
||||
window.socket.on('item.renamed', async (item) => {
|
||||
if ( item.original_client_socket_id === window.socket.id ) return;
|
||||
|
||||
const $el = $(`.item[data-uid='${item.uid}']`);
|
||||
if ( $el.length === 0 ) return;
|
||||
|
||||
// Update data attributes
|
||||
$el.attr('data-name', html_encode(item.name));
|
||||
$el.attr('data-path', html_encode(item.path));
|
||||
|
||||
// Update displayed name
|
||||
$el.find('.item-name').text(item.name);
|
||||
$el.find('.item-name-editor').val(item.name);
|
||||
});
|
||||
|
||||
window.socket.on('item.updated', async (item) => {
|
||||
const $el = $(`.item[data-uid='${item.uid}']`);
|
||||
if ( $el.length === 0 ) return;
|
||||
|
||||
// Update data attributes
|
||||
$el.attr('data-name', html_encode(item.name));
|
||||
$el.attr('data-path', html_encode(item.path));
|
||||
$el.attr('data-size', item.size);
|
||||
$el.attr('data-modified', item.modified);
|
||||
$el.attr('data-type', html_encode(item.type));
|
||||
|
||||
// Update displayed name
|
||||
$el.find('.item-name').text(item.name);
|
||||
$el.find('.item-name-editor').val(item.name);
|
||||
|
||||
if (
|
||||
window.dashboard_object?.currentView === 'grid'
|
||||
&& typeof item.thumbnail === 'string'
|
||||
&& item.thumbnail.length > 0
|
||||
) {
|
||||
$el.find('.item-icon img').attr('src', item.thumbnail);
|
||||
}
|
||||
});
|
||||
|
||||
window.socket.on('item.added', async (item) => {
|
||||
if ( !item || Object.keys(item).length === 0 ) return;
|
||||
if ( item.original_client_socket_id === window.socket.id ) return;
|
||||
|
||||
if ( window.UIDashboardFileItem ) {
|
||||
window.UIDashboardFileItem(item);
|
||||
}
|
||||
});
|
||||
|
||||
// Apply initial route from URL - activate the correct tab
|
||||
if ( window.dashboard_initial_route ) {
|
||||
const route = window.dashboard_initial_route;
|
||||
@@ -356,7 +258,6 @@ async function UIDashboard (options) {
|
||||
const handleRouteChange = () => {
|
||||
const route = window.parseDashboardRoute();
|
||||
const tab = route.tab;
|
||||
const filePath = route.path;
|
||||
|
||||
// Switch to correct tab
|
||||
const $targetTab = $el_window.find(`.dashboard-sidebar-item[data-section="${tab}"]`);
|
||||
@@ -378,14 +279,6 @@ async function UIDashboard (options) {
|
||||
|
||||
// Scroll content area to top
|
||||
$el_window.find('.dashboard-content').scrollTop(0);
|
||||
|
||||
// If files tab with path, navigate without adding to history
|
||||
if ( tab === 'files' && filePath ) {
|
||||
const filesTab = tabs.find(t => t.id === 'files');
|
||||
if ( filesTab?.renderDirectory ) {
|
||||
filesTab.renderDirectory(filePath, { skipUrlUpdate: true, skipNavHistory: true });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for both hashchange and popstate to handle all navigation scenarios
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1910,19 +1910,6 @@ span.header-sort-icon img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* TabFiles rubber band selection area */
|
||||
.tabfiles-selection-area {
|
||||
background-color: rgba(59, 130, 246, 0.15);
|
||||
border: 1px solid var(--select-color);
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dashboard-section-files .files {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@@ -1735,10 +1735,6 @@ window.move_items = async function (el_items, dest_path, is_undo = false) {
|
||||
suggested_apps: fsentry.suggested_apps,
|
||||
};
|
||||
UIItem(options);
|
||||
// In dashboard mode, also create item via dashboard's renderer
|
||||
if ( window.is_dashboard_mode && window.UIDashboardFileItem ) {
|
||||
window.UIDashboardFileItem(fsentry);
|
||||
}
|
||||
moved_items.push({ 'options': options, 'original_path': $(el_item).attr('data-path') });
|
||||
|
||||
// this operation may have created some missing directories,
|
||||
@@ -1764,10 +1760,6 @@ window.move_items = async function (el_items, dest_path, is_undo = false) {
|
||||
suggested_apps: dir.suggested_apps,
|
||||
});
|
||||
}
|
||||
// In dashboard mode, also create parent dirs via dashboard's renderer
|
||||
if ( window.is_dashboard_mode && window.UIDashboardFileItem ) {
|
||||
window.UIDashboardFileItem(dir);
|
||||
}
|
||||
window.sort_items(item_container);
|
||||
});
|
||||
|
||||
|
||||
+6
-12
@@ -160,21 +160,15 @@ if ( window.location.pathname === '/dashboard' || window.location.pathname === '
|
||||
|
||||
/**
|
||||
* Parses the dashboard URL hash into a route object.
|
||||
* Hash format: #files/username/Documents or #usage or #account etc.
|
||||
* @returns {{ tab: string, path: string|null }} Route object with tab name and optional file path
|
||||
* Hash format: #usage or #account etc.
|
||||
* @returns {{ tab: string }} Route object with tab name
|
||||
*/
|
||||
function parseDashboardRoute () {
|
||||
const hash = decodeURIComponent(window.location.hash.slice(1)); // Remove '#' and decode URL encoding
|
||||
if ( ! hash ) return { tab: 'home', path: null };
|
||||
const hash = decodeURIComponent(window.location.hash.slice(1));
|
||||
if ( ! hash ) return { tab: 'home' };
|
||||
|
||||
const parts = hash.split('/').filter(Boolean); // ['files', 'username', 'Documents']
|
||||
const tab = parts[0]; // 'files', 'usage', 'account', 'security'
|
||||
|
||||
if ( tab === 'files' && parts.length > 1 ) {
|
||||
const filePath = `/${parts.slice(1).join('/')}`; // /username/Documents
|
||||
return { tab: 'files', path: filePath };
|
||||
}
|
||||
return { tab: tab || 'home', path: null };
|
||||
const tab = hash.split('/').filter(Boolean)[0];
|
||||
return { tab: tab || 'home' };
|
||||
}
|
||||
|
||||
// Make parseDashboardRoute available globally for hashchange handler
|
||||
|
||||
Reference in New Issue
Block a user