mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-05 17:10:45 +00:00
Add 'Open in AI' option to item context menus (#1974)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled
* Add 'Open in AI' option to item context menus * Add new AI-related English translations
This commit is contained in:
@@ -32,7 +32,82 @@ import launch_app from '../helpers/launch_app.js';
|
||||
import open_item from '../helpers/open_item.js';
|
||||
import mime from '../lib/mime.js';
|
||||
|
||||
function UIItem (options) {
|
||||
const AI_APP_NAME = 'ai';
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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')),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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',
|
||||
}, '*');
|
||||
};
|
||||
|
||||
function UIItem(options){
|
||||
const matching_appendto_count = $(options.appendTo).length;
|
||||
if ( matching_appendto_count > 1 ) {
|
||||
$(options.appendTo).each(function () {
|
||||
@@ -909,6 +984,15 @@ function UIItem (options) {
|
||||
},
|
||||
});
|
||||
// -------------------------------------------
|
||||
// Open in AI
|
||||
// -------------------------------------------
|
||||
menu_items.push({
|
||||
html: i18n('open_in_ai'),
|
||||
onClick: async function(){
|
||||
await sendSelectionToAIApp($selected_items);
|
||||
}
|
||||
});
|
||||
// -------------------------------------------
|
||||
// -
|
||||
// -------------------------------------------
|
||||
menu_items.push({ is_divider: true });
|
||||
@@ -1243,6 +1327,15 @@ function UIItem (options) {
|
||||
UIWindowShare([{ uid: $(el_item).attr('data-uid'), path: $(el_item).attr('data-path'), name: $(el_item).attr('data-name'), icon: $(el_item_icon).find('img').attr('src') }]);
|
||||
},
|
||||
});
|
||||
// -------------------------------------------
|
||||
// Open in AI
|
||||
// -------------------------------------------
|
||||
menu_items.push({
|
||||
html: i18n('open_in_ai'),
|
||||
onClick: async function(){
|
||||
await sendSelectionToAIApp($(el_item));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
@@ -1837,4 +1930,4 @@ window.activate_item_name_editor = function (el_item) {
|
||||
}
|
||||
};
|
||||
|
||||
export default UIItem;
|
||||
export default UIItem;
|
||||
|
||||
@@ -27,6 +27,7 @@ const en = {
|
||||
account_password: 'Verify Account Password',
|
||||
access_granted_to: 'Access Granted To',
|
||||
add_existing_account: 'Add Existing Account',
|
||||
ai_app_unavailable: 'AI app is not available. Please try again later.',
|
||||
all_fields_required: 'All fields are required.',
|
||||
allow: 'Allow',
|
||||
apply: 'Apply',
|
||||
@@ -194,6 +195,7 @@ const en = {
|
||||
ok: 'OK',
|
||||
open: 'Open',
|
||||
new_window: 'New Window',
|
||||
open_in_ai: 'Open in AI',
|
||||
open_in_new_tab: 'Open in New Tab',
|
||||
open_in_new_window: 'Open in New Window',
|
||||
open_trash: 'Open Trash',
|
||||
@@ -426,7 +428,6 @@ const en = {
|
||||
'billing.currently_on_free_plan': 'You are currently on the free plan.',
|
||||
'billing.download_receipt': 'Download Receipt',
|
||||
'billing.subscription_check_error': 'A problem occurred while checking your subscription status.',
|
||||
'billing.payment_method_updated': 'Payment method updated!',
|
||||
'billing.email_confirmation_needed': 'Your email has not been confirmed. We\'ll send you a code to confirm it now.',
|
||||
'billing.sub_cancelled_but_valid_until': 'You have cancelled your subscription and it will automatically switch to the free tier at the end of the billing period. You will not be charged again unless you re-subscribe.',
|
||||
'billing.current_plan_until_end_of_period': 'Your current plan until the end of this billing period.',
|
||||
@@ -537,4 +538,4 @@ const en = {
|
||||
},
|
||||
};
|
||||
|
||||
export default en;
|
||||
export default en;
|
||||
|
||||
Reference in New Issue
Block a user