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:
Eric Dubé
2024-04-09 21:31:48 -04:00
committed by GitHub
3 changed files with 77 additions and 6 deletions

View File

@@ -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});
}
});

View File

@@ -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

View File

@@ -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);