Trim file context menu actions

This commit is contained in:
jelveh
2026-07-17 14:23:52 -07:00
parent cba6ac8184
commit 172aa01e1c
@@ -27,102 +27,8 @@ import UIWindowPublishWorker from '../UI/UIWindowPublishWorker.js';
import open_item from './open_item.js';
import launch_app from './launch_app.js';
import path from '../lib/path.js';
import mime from '../lib/mime.js';
import { isWeblinkName, weblinkChangeIconMenuItem } from './weblink.js';
const AI_APP_NAME = 'ai';
/**
* Parses item metadata for AI payload
* @param {string} metadata - JSON string of metadata
* @returns {Object|undefined} Parsed metadata or undefined
*/
const parseItemMetadataForAI = (metadata) => {
if ( ! metadata ) {
return undefined;
}
try {
return JSON.parse(metadata);
} catch ( error ) {
console.warn('Failed to parse item metadata for AI payload.', error);
return undefined;
}
};
/**
* Builds AI payload from item elements
* @param {jQuery} $elements - jQuery collection of elements
* @returns {Array} Array of item data for AI
*/
const buildAIPayloadFromItems = ($elements) => {
return $elements.get().map((element) => {
const $element = $(element);
return {
uid: $element.attr('data-uid'),
path: $element.attr('data-path'),
name: $element.attr('data-name'),
is_dir: $element.attr('data-is_dir') === '1',
is_shortcut: $element.attr('data-is_shortcut') === '1',
shortcut_to: $element.attr('data-shortcut_to') || undefined,
shortcut_to_path: $element.attr('data-shortcut_to_path') || undefined,
size: $element.attr('data-size') || undefined,
type: $element.attr('data-type') || undefined,
modified: $element.attr('data-modified') || undefined,
metadata: parseItemMetadataForAI($element.attr('data-metadata')),
};
});
};
/**
* Ensures AI app iframe is available
* @returns {Promise<HTMLIFrameElement|null>} AI app iframe or null
*/
const ensureAIAppIframe = async () => {
let $aiWindow = $(`.window[data-app="${AI_APP_NAME}"]`);
if ( $aiWindow.length === 0 ) {
try {
await launch_app({ name: AI_APP_NAME });
} catch ( error ) {
console.error('Failed to launch AI app.', error);
return null;
}
$aiWindow = $(`.window[data-app="${AI_APP_NAME}"]`);
}
if ( $aiWindow.length === 0 ) {
return null;
}
$aiWindow.makeWindowVisible();
const iframe = $aiWindow.find('.window-app-iframe').get(0);
return iframe ?? null;
};
/**
* Sends selection to AI app
* @param {jQuery} $elements - jQuery collection of elements
*/
const sendSelectionToAIApp = async ($elements) => {
const items = buildAIPayloadFromItems($elements);
if ( items.length === 0 ) {
return;
}
const aiIframe = await ensureAIAppIframe();
if ( !aiIframe || !aiIframe.contentWindow ) {
await UIAlert({
message: i18n('ai_app_unavailable'),
});
return;
}
aiIframe.contentWindow.postMessage({
msg: 'ai:openFsEntries',
items,
source: 'desktop-context-menu',
}, '*');
};
/**
* Generates context menu items for file/folder operations
*
@@ -187,40 +93,6 @@ const generate_file_context_menu = async function (options) {
menu_items.push('-');
}
// -------------------------------------------
// Open in New Window
// (only if the item is on a window)
// -------------------------------------------
if ( $(el_item).closest('.window-body').length > 0 && fsentry.is_dir ) {
menu_items.push({
html: i18n('open_in_new_window'),
onClick: function () {
if ( fsentry.is_dir ) {
open_item({ item: el_item, new_window: true });
}
},
});
// -------------------------------------------
// Separator
// -------------------------------------------
if ( !is_trash && !is_trashed && fsentry.is_dir ) {
menu_items.push('-');
}
}
// -------------------------------------------
// Open in AI
// -------------------------------------------
if ( !is_trashed && !is_trash ) {
menu_items.push({
html: i18n('open_in_ai'),
onClick: async function () {
await sendSelectionToAIApp($(el_item));
},
});
}
// -------------------------------------------
// Publish As Website
// -------------------------------------------
@@ -330,107 +202,6 @@ const generate_file_context_menu = async function (options) {
});
}
// -------------------------------------------
// Set as Wallpaper
// -------------------------------------------
const mime_type = mime.getType($(el_item).attr('data-name')) ?? 'application/octet-stream';
if ( !is_trashed && !is_trash && !fsentry.is_dir && mime_type.startsWith('image/') ) {
menu_items.push({
html: i18n('set_as_background'),
onClick: async function () {
const read_url = await puter.fs.sign(undefined, { uid: $(el_item).attr('data-uid'), action: 'read' });
window.set_desktop_background({
url: read_url.items.read_url,
fit: window.desktop_bg_fit,
});
// Update dashboard desktop view background if visible
const $desktopView = $('.files.desktop-view');
if ( $desktopView.length ) {
$desktopView.css({
'background-image': `url(${read_url.items.read_url})`,
'background-size': (window.desktop_bg_fit === 'repeat') ? 'auto' : (window.desktop_bg_fit || 'cover'),
'background-repeat': (window.desktop_bg_fit === 'repeat') ? 'repeat' : 'no-repeat',
'background-position': 'center center',
'background-color': '',
});
}
try {
$.ajax({
url: `${window.api_origin}/set-desktop-bg`,
type: 'POST',
data: JSON.stringify({
url: window.desktop_bg_url,
color: window.desktop_bg_color,
fit: window.desktop_bg_fit,
}),
async: true,
contentType: 'application/json',
headers: {
'Authorization': `Bearer ${window.auth_token}`,
},
statusCode: {
401: function (xhr) {
window.handle401(xhr);
},
},
});
} catch ( err ) {
// Ignore
}
},
});
}
// -------------------------------------------
// Zip
// -------------------------------------------
if ( !is_trash && !is_trashed && !$(el_item).attr('data-path').endsWith('.zip') ) {
menu_items.push({
html: i18n('zip'),
onClick: function () {
window.zipItems(el_item, path.dirname($(el_item).attr('data-path')), false);
},
});
}
// -------------------------------------------
// Unzip
// -------------------------------------------
if ( !is_trash && !is_trashed && $(el_item).attr('data-path').endsWith('.zip') ) {
menu_items.push({
html: i18n('unzip'),
onClick: async function () {
let filePath = $(el_item).attr('data-path');
window.unzipItem(filePath);
},
});
}
// -------------------------------------------
// Tar
// -------------------------------------------
if ( !is_trash && !is_trashed && !$(el_item).attr('data-path').endsWith('.tar') ) {
menu_items.push({
html: i18n('tar'),
onClick: function () {
window.tarItems(el_item, path.dirname($(el_item).attr('data-path')), false);
},
});
}
// -------------------------------------------
// Untar
// -------------------------------------------
if ( !is_trash && !is_trashed && $(el_item).attr('data-path').endsWith('.tar') ) {
menu_items.push({
html: i18n('untar'),
onClick: async function () {
let filePath = $(el_item).attr('data-path');
window.untarItem(filePath);
},
});
}
// -------------------------------------------
// Restore
// -------------------------------------------