mirror of
https://github.com/HeyPuter/puter.git
synced 2026-03-12 21:20:07 -05:00
Merge pull request #255 from AtkinsSJ/appconnection-close
Notify apps when a child app closes, and let them close their children manually
This commit is contained in:
51
src/IPC.js
51
src/IPC.js
@@ -74,11 +74,15 @@ window.addEventListener('message', async (event) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const iframe_for_app_instance = (instanceID) => {
|
||||
return $(`.window[data-element_uuid="${instanceID}"]`).find('.window-app-iframe').get(0)
|
||||
const window_for_app_instance = (instance_id) => {
|
||||
return $(`.window[data-element_uuid="${instance_id}"]`).get(0);
|
||||
};
|
||||
|
||||
const $el_parent_window = $(`.window[data-element_uuid="${event.data.appInstanceID}"]`);
|
||||
const iframe_for_app_instance = (instance_id) => {
|
||||
return $(window_for_app_instance(instance_id)).find('.window-app-iframe').get(0);
|
||||
};
|
||||
|
||||
const $el_parent_window = $(window_for_app_instance(event.data.appInstanceID));
|
||||
const parent_window_id = $el_parent_window.attr('data-id');
|
||||
const $el_parent_disable_mask = $el_parent_window.find('.window-disable-mask');
|
||||
const target_iframe = iframe_for_app_instance(event.data.appInstanceID);
|
||||
@@ -357,7 +361,7 @@ window.addEventListener('message', async (event) => {
|
||||
// setWindowTitle
|
||||
//--------------------------------------------------------
|
||||
else if(event.data.msg === 'setWindowTitle' && event.data.new_title !== undefined){
|
||||
const el_window = $(`.window[data-element_uuid="${event.data.appInstanceID}"]`).get(0);
|
||||
const el_window = window_for_app_instance(event.data.appInstanceID);
|
||||
// set window title
|
||||
$(el_window).find(`.window-head-title`).html(html_encode(event.data.new_title));
|
||||
// send confirmation to requester window
|
||||
@@ -1099,11 +1103,48 @@ window.addEventListener('message', async (event) => {
|
||||
contents,
|
||||
}, targetAppOrigin);
|
||||
}
|
||||
//--------------------------------------------------------
|
||||
// closeApp
|
||||
//--------------------------------------------------------
|
||||
else if (event.data.msg === 'closeApp') {
|
||||
const { appInstanceID, targetAppInstanceID } = event.data;
|
||||
|
||||
const target_window = window_for_app_instance(targetAppInstanceID);
|
||||
if (!target_window) {
|
||||
console.warn(`Failed to close non-existent app ${targetAppInstanceID}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
const allowed = (() => {
|
||||
// Parents can close their children
|
||||
if (target_window.dataset['parent_instance_id']) {
|
||||
console.log(`⚠️ Allowing app ${appInstanceID} to close child app ${targetAppInstanceID}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// God-mode apps can close anything
|
||||
const app_info = await get_apps(app_name);
|
||||
if (app_info.godmode === 1) {
|
||||
console.log(`⚠️ Allowing GODMODE app ${appInstanceID} to close app ${targetAppInstanceID}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: What other situations should we allow?
|
||||
return false;
|
||||
})();
|
||||
|
||||
if (allowed) {
|
||||
$(target_window).close();
|
||||
} else {
|
||||
console.warn(`⚠️ App ${appInstanceID} is not permitted to close app ${targetAppInstanceID}`);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// exit
|
||||
//--------------------------------------------------------
|
||||
else if(event.data.msg === 'exit'){
|
||||
$(`.window[data-element_uuid="${event.data.appInstanceID}"]`).close({bypass_iframe_messaging: true});
|
||||
$(window_for_app_instance(event.data.appInstanceID)).close({bypass_iframe_messaging: true});
|
||||
}
|
||||
});
|
||||
@@ -185,6 +185,7 @@ async function UIWindow(options) {
|
||||
data-uid ="${options.uid}"
|
||||
data-element_uuid="${options.element_uuid}"
|
||||
data-parent_uuid="${options.parent_uuid}"
|
||||
${options.parent_instance_id ? `data-parent_instance_id="${options.parent_instance_id}"` : ''}
|
||||
data-id ="${win_id}"
|
||||
data-iframe_msg_uid ="${options.iframe_msg_uid}"
|
||||
data-is_dir ="${options.is_dir}"
|
||||
@@ -2745,8 +2746,9 @@ $.fn.close = async function(options) {
|
||||
options = options || {};
|
||||
$(this).each(async function() {
|
||||
const el_iframe = $(this).find('.window-app-iframe');
|
||||
const app_uses_sdk = el_iframe.length > 0 && el_iframe.attr('data-appUsesSDK') === 'true';
|
||||
// tell child app that this window is about to close, get its response
|
||||
if(el_iframe.length > 0 && el_iframe.attr('data-appUsesSDK') === 'true'){
|
||||
if(app_uses_sdk){
|
||||
if(!options.bypass_iframe_messaging){
|
||||
const resp = await sendWindowWillCloseMsg(el_iframe.get(0));
|
||||
if(!resp.msg){
|
||||
@@ -2819,6 +2821,30 @@ $.fn.close = async function(options) {
|
||||
}
|
||||
// close child windows
|
||||
$(`.window[data-parent_uuid="${window_uuid}"]`).close();
|
||||
|
||||
// notify other apps that we're closing
|
||||
if (app_uses_sdk) {
|
||||
// notify parent app, if we have one, that we're closing
|
||||
const parent_id = this.dataset['parent_instance_id'];
|
||||
const parent = $(`.window[data-element_uuid="${parent_id}"] .window-app-iframe`).get(0);
|
||||
if (parent) {
|
||||
parent.contentWindow.postMessage({
|
||||
msg: 'appClosed',
|
||||
appInstanceID: window_uuid,
|
||||
}, '*');
|
||||
}
|
||||
|
||||
// notify child apps, if we have them, that we're closing
|
||||
const children = $(`.window[data-parent_instance_id="${window_uuid}"] .window-app-iframe`);
|
||||
children.each((_, child) => {
|
||||
child.contentWindow.postMessage({
|
||||
msg: 'appClosed',
|
||||
appInstanceID: window_uuid,
|
||||
}, '*');
|
||||
});
|
||||
// TODO: Once other AppConnections exist, those will need notifying too.
|
||||
}
|
||||
|
||||
// remove backdrop
|
||||
$(this).closest('.window-backdrop').remove();
|
||||
// remove DOM element
|
||||
|
||||
@@ -1860,6 +1860,10 @@ window.launch_app = async (options)=>{
|
||||
let icon, title, file_signature;
|
||||
const window_options = options.window_options ?? {};
|
||||
|
||||
if (options.parent_instance_id) {
|
||||
window_options.parent_instance_id = options.parent_instance_id;
|
||||
}
|
||||
|
||||
// try to get 3rd-party app info
|
||||
let app_info = options.app_obj ?? await get_apps(options.name);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user