Skip to content

Commit 7323159

Browse files
committed
Add 'Open in AI' option to item context menus
1 parent 52978d4 commit 7323159

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

src/gui/src/UI/UIItem.js

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,81 @@ import launch_app from "../helpers/launch_app.js"
3232
import open_item from "../helpers/open_item.js"
3333
import mime from "../lib/mime.js";
3434

35+
const AI_APP_NAME = 'ai';
36+
37+
const parseItemMetadataForAI = (metadata) => {
38+
if (!metadata) {
39+
return undefined;
40+
}
41+
try {
42+
return JSON.parse(metadata);
43+
} catch (error) {
44+
console.warn('Failed to parse item metadata for AI payload.', error);
45+
return undefined;
46+
}
47+
};
48+
49+
const buildAIPayloadFromItems = ($elements) => {
50+
return $elements.get().map((element) => {
51+
const $element = $(element);
52+
return {
53+
uid: $element.attr('data-uid'),
54+
path: $element.attr('data-path'),
55+
name: $element.attr('data-name'),
56+
is_dir: $element.attr('data-is_dir') === '1',
57+
is_shortcut: $element.attr('data-is_shortcut') === '1',
58+
shortcut_to: $element.attr('data-shortcut_to') || undefined,
59+
shortcut_to_path: $element.attr('data-shortcut_to_path') || undefined,
60+
size: $element.attr('data-size') || undefined,
61+
type: $element.attr('data-type') || undefined,
62+
modified: $element.attr('data-modified') || undefined,
63+
metadata: parseItemMetadataForAI($element.attr('data-metadata')),
64+
};
65+
});
66+
};
67+
68+
const ensureAIAppIframe = async () => {
69+
let $aiWindow = $(`.window[data-app="${AI_APP_NAME}"]`);
70+
if ($aiWindow.length === 0) {
71+
try {
72+
await launch_app({ name: AI_APP_NAME });
73+
} catch (error) {
74+
console.error('Failed to launch AI app.', error);
75+
return null;
76+
}
77+
$aiWindow = $(`.window[data-app="${AI_APP_NAME}"]`);
78+
}
79+
80+
if ($aiWindow.length === 0) {
81+
return null;
82+
}
83+
84+
$aiWindow.makeWindowVisible();
85+
const iframe = $aiWindow.find('.window-app-iframe').get(0);
86+
return iframe ?? null;
87+
};
88+
89+
const sendSelectionToAIApp = async ($elements) => {
90+
const items = buildAIPayloadFromItems($elements);
91+
if (items.length === 0) {
92+
return;
93+
}
94+
95+
const aiIframe = await ensureAIAppIframe();
96+
if (!aiIframe || !aiIframe.contentWindow) {
97+
await UIAlert({
98+
message: i18n('ai_app_unavailable'),
99+
});
100+
return;
101+
}
102+
103+
aiIframe.contentWindow.postMessage({
104+
msg: 'ai:openFsEntries',
105+
items,
106+
source: 'desktop-context-menu',
107+
}, '*');
108+
};
109+
35110
function UIItem(options){
36111
const matching_appendto_count = $(options.appendTo).length;
37112
if(matching_appendto_count > 1){
@@ -850,6 +925,15 @@ function UIItem(options){
850925
}
851926
})
852927
// -------------------------------------------
928+
// Open in AI
929+
// -------------------------------------------
930+
menu_items.push({
931+
html: i18n('open_in_ai'),
932+
onClick: async function(){
933+
await sendSelectionToAIApp($selected_items);
934+
}
935+
});
936+
// -------------------------------------------
853937
// -
854938
// -------------------------------------------
855939
menu_items.push({ is_divider: true });
@@ -1178,6 +1262,15 @@ function UIItem(options){
11781262
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')}]);
11791263
}
11801264
});
1265+
// -------------------------------------------
1266+
// Open in AI
1267+
// -------------------------------------------
1268+
menu_items.push({
1269+
html: i18n('open_in_ai'),
1270+
onClick: async function(){
1271+
await sendSelectionToAIApp($(el_item));
1272+
}
1273+
});
11811274
}
11821275

11831276
// -------------------------------------------
@@ -1753,4 +1846,4 @@ window.activate_item_name_editor= function(el_item){
17531846
$(el_item_name_editor).select();
17541847
}
17551848

1756-
export default UIItem;
1849+
export default UIItem;

src/gui/src/i18n/translations/en.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ const en = {
137137
enter_password_to_confirm_delete_user: "Enter your password to confirm account deletion",
138138
error_message_is_missing: "Error message is missing.",
139139
error_unknown_cause: "An unknown error occurred.",
140+
ai_app_unavailable: "The AI app isn't available right now. Please try again in a moment.",
140141
error_uploading_files: "Failed to upload files",
141142
favorites: "Favorites",
142143
feedback: "Feedback",
@@ -197,6 +198,7 @@ const en = {
197198
new_window: "New Window",
198199
open_in_new_tab: "Open in New Tab",
199200
open_in_new_window: "Open in New Window",
201+
open_in_ai: "Open in AI",
200202
open_trash: "Open Trash",
201203
open_with: "Open With",
202204
original_name: 'Original Name',
@@ -520,4 +522,4 @@ const en = {
520522
}
521523
};
522524

523-
export default en;
525+
export default en;

0 commit comments

Comments
 (0)