mirror of
https://github.com/HeyPuter/puter.git
synced 2026-09-26 23:26:04 +00:00
dev: implement GUI behavior to fetch subdomains later
This change makes GUI invoke readdir without fetching subdomains, and then fetch subdomains after. This allows displaying the directory items sooner and then later populating the icons with glyphs to indicate if there is an associated subdomain. This was AI-assisted with manual modifications and bug fixes as necessary.
This commit is contained in:
@@ -1866,6 +1866,138 @@ window.update_sites_cache = function () {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches subdomains for directories and updates UI items with subdomain data.
|
||||
* This function can be called after readdir to update website badges asynchronously.
|
||||
*
|
||||
* @param {Array} fsentries - Array of filesystem entries (from readdir)
|
||||
* @param {jQuery|HTMLElement} [container] - Optional container to limit search scope. If not provided, searches entire document.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
window.updateSubdomainsForItems = async function (fsentries, container) {
|
||||
if ( !fsentries || fsentries.length === 0 ) {
|
||||
console.log('[updateSubdomainsForItems] No fsentries provided');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[updateSubdomainsForItems] Starting update for ${fsentries.length} entries, container:`, container);
|
||||
|
||||
// Extract directory IDs and create a map of id -> fsentry
|
||||
const directoryIds = [];
|
||||
const fsentryById = new Map();
|
||||
|
||||
for ( const fsentry of fsentries ) {
|
||||
if ( fsentry.is_dir && fsentry.id != null ) {
|
||||
directoryIds.push(fsentry.id);
|
||||
fsentryById.set(fsentry.id, fsentry);
|
||||
}
|
||||
}
|
||||
|
||||
if ( directoryIds.length === 0 ) {
|
||||
console.log('[updateSubdomainsForItems] No directories found in fsentries');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[updateSubdomainsForItems] Fetching subdomains for ${directoryIds.length} directories:`, directoryIds);
|
||||
|
||||
try {
|
||||
const subdomainResults = await puter.fs.readdirSubdomains({ directory_ids: directoryIds });
|
||||
console.log('[updateSubdomainsForItems] Subdomain results:', subdomainResults);
|
||||
|
||||
// Create a map of directory_id -> subdomain data
|
||||
const subdomainMap = new Map();
|
||||
for ( const result of subdomainResults ) {
|
||||
subdomainMap.set(result.directory_id, {
|
||||
subdomains: result.subdomains,
|
||||
has_website: result.has_website,
|
||||
});
|
||||
}
|
||||
|
||||
// Update UI items with subdomain data
|
||||
// Always search entire document first to ensure we find items regardless of DOM structure
|
||||
for ( const fsentry of fsentries ) {
|
||||
if ( !fsentry.is_dir || !fsentry.id ) continue;
|
||||
|
||||
const subdomainData = subdomainMap.get(fsentry.id);
|
||||
const has_website = subdomainData ? subdomainData.has_website : false;
|
||||
const subdomains = subdomainData ? subdomainData.subdomains : [];
|
||||
|
||||
console.log('[updateSubdomainsForItems] Processing directory:', {
|
||||
name: fsentry.name,
|
||||
uid: fsentry.uid,
|
||||
id: fsentry.id,
|
||||
path: fsentry.path,
|
||||
has_website: has_website,
|
||||
subdomains_count: subdomains.length,
|
||||
});
|
||||
|
||||
// Find the item element - search entire document by uid first
|
||||
let $item = $(document).find(`.item[data-uid="${fsentry.uid}"]`);
|
||||
console.log(`[updateSubdomainsForItems] Search by uid "${fsentry.uid}": found ${$item.length} item(s)`);
|
||||
|
||||
// If not found by uid, try path-based search
|
||||
if ( $item.length === 0 && fsentry.path ) {
|
||||
// Escape special characters in path for jQuery selector
|
||||
const escapedPath = fsentry.path.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
|
||||
$item = $(document).find(`.item[data-path="${escapedPath}"]`);
|
||||
console.log(`[updateSubdomainsForItems] Search by path "${fsentry.path}": found ${$item.length} item(s)`);
|
||||
}
|
||||
|
||||
// Debug: Check all items with matching uid in document
|
||||
if ( $item.length === 0 ) {
|
||||
const allItemsWithUid = $(document).find('.item[data-uid]');
|
||||
const matchingUids = Array.from(allItemsWithUid).map(el => $(el).attr('data-uid')).filter(uid => uid === fsentry.uid);
|
||||
console.log(`[updateSubdomainsForItems] Debug - Total items with data-uid in document: ${allItemsWithUid.length}, items with matching uid "${fsentry.uid}": ${matchingUids.length}`);
|
||||
|
||||
if ( fsentry.path ) {
|
||||
const allItemsWithPath = $(document).find('.item[data-path]');
|
||||
const matchingPaths = Array.from(allItemsWithPath).map(el => $(el).attr('data-path')).filter(path => path === fsentry.path);
|
||||
console.log(`[updateSubdomainsForItems] Debug - Total items with data-path in document: ${allItemsWithPath.length}, items with matching path "${fsentry.path}": ${matchingPaths.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $item.length > 0 ) {
|
||||
console.log(`[updateSubdomainsForItems] ✓ Found item, updating has_website to ${has_website}`);
|
||||
|
||||
// Update has_website attribute
|
||||
$item.attr('data-has_website', has_website ? '1' : '0');
|
||||
|
||||
// Update website badge visibility
|
||||
const $badge = $item.find('.item-has-website-badge');
|
||||
if ( $badge.length > 0 ) {
|
||||
$badge.css('display', has_website ? 'block' : 'none');
|
||||
console.log(`[updateSubdomainsForItems] ✓ Updated badge visibility: ${has_website ? 'visible' : 'hidden'}`);
|
||||
} else {
|
||||
console.log('[updateSubdomainsForItems] ⚠ Badge element not found in item');
|
||||
}
|
||||
|
||||
// Update cache with subdomain data
|
||||
if ( fsentry.path ) {
|
||||
const cachedItem = await puter._cache.get(`item:${fsentry.path}`);
|
||||
if ( cachedItem ) {
|
||||
cachedItem.subdomains = subdomains;
|
||||
cachedItem.has_website = has_website;
|
||||
puter._cache.set(`item:${fsentry.path}`, cachedItem);
|
||||
console.log(`[updateSubdomainsForItems] ✓ Updated cache for path: ${fsentry.path}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('[updateSubdomainsForItems] ✗ Item not found for directory:', {
|
||||
name: fsentry.name,
|
||||
uid: fsentry.uid,
|
||||
id: fsentry.id,
|
||||
path: fsentry.path,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[updateSubdomainsForItems] Update complete');
|
||||
} catch ( error ) {
|
||||
// Silently fail subdomain fetching - don't block the UI
|
||||
console.error('[updateSubdomainsForItems] Failed to fetch subdomains:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} el_target_container
|
||||
|
||||
@@ -113,8 +113,8 @@ const refresh_item_container = function (el_item_container, options) {
|
||||
// remove all existing items
|
||||
$(el_item_container).find('.item').removeItems();
|
||||
|
||||
// get items
|
||||
puter.fs.readdir({ path: container_path, consistency: options.consistency ?? 'eventual' }).then((fsentries) => {
|
||||
// get items (skip subdomain fetching for faster response)
|
||||
puter.fs.readdir({ path: container_path, consistency: options.consistency ?? 'eventual', no_subdomains: true }).then(async (fsentries) => {
|
||||
// Check if the same folder is still loading since el_item_container's
|
||||
// data-path might have changed by other operations while waiting for the response to this `readdir`.
|
||||
if ( $(el_item_container).attr('data-path') !== container_path )
|
||||
@@ -242,6 +242,13 @@ const refresh_item_container = function (el_item_container, options) {
|
||||
$(el_item_container).attr('data-sort_by'),
|
||||
$(el_item_container).attr('data-sort_order'));
|
||||
|
||||
// Fetch subdomains separately for directories and update UI
|
||||
// Use the reusable function to update subdomains
|
||||
// Note: This is fire-and-forget - it will update items asynchronously
|
||||
window.updateSubdomainsForItems(fsentries, el_item_container).catch(err => {
|
||||
console.warn('Failed to update subdomains for items:', err);
|
||||
});
|
||||
|
||||
if ( options.fadeInItems ) {
|
||||
$(el_item_container).animate({ 'opacity': '1' }, {
|
||||
complete: () => {
|
||||
|
||||
Reference in New Issue
Block a user