diff --git a/src/dev-center/js/dev-center.js b/src/dev-center/js/dev-center.js index 3cff4fc0..22aba17a 100644 --- a/src/dev-center/js/dev-center.js +++ b/src/dev-center/js/dev-center.js @@ -157,6 +157,9 @@ function refresh_app_list(show_loading = false) { $('#loading').show(); // get apps setTimeout(function () { + // uncheck the select all checkbox + $('.select-all-apps').prop('checked', false); + puter.apps.list().then((apps_res) => { $('#loading').hide(); apps = apps_res; @@ -342,8 +345,22 @@ $(document).on('click', '.delete-app', async function (e) { let app_title = $(this).attr('data-app-title'); let app_name = $(this).attr('data-app-name'); + // get app + const app_data = await puter.apps.get(app_name); + + if(app_data.metadata?.locked){ + puter.ui.alert(`${app_data.title} is locked and cannot be deleted.`, [ + { + label: 'Ok', + }, + ], { + type: 'warning', + }); + return; + } + // confirm delete - const alert_resp = await puter.ui.alert(`Are you sure you want to premanently delete "${html_encode(app_title)}"?`, + const alert_resp = await puter.ui.alert(`Are you sure you want to premanently delete ${html_encode(app_title)}?`, [ { label: 'Yes, delete permanently', @@ -360,8 +377,7 @@ $(document).on('click', '.delete-app', async function (e) { let init_ts = Date.now(); $('.deleting-app-modal')?.get(0)?.showModal(); puter.apps.delete(app_name).then(async (app) => { - setTimeout( - () => { + setTimeout(() => { $('.deleting-app-modal')?.get(0)?.close(); $(`.app-card[data-uid="${app_uid}"]`).fadeOut(200, function name(params) { $(this).remove(); @@ -375,8 +391,8 @@ $(document).on('click', '.delete-app', async function (e) { count_apps(); }); }, - // make sure the modal was shown for at least 2 seconds - (Date.now() - init_ts) > 2000 ? 1 : 2000 - (Date.now() - init_ts)); + // make sure the modal was shown for at least 2 seconds + (Date.now() - init_ts) > 2000 ? 1 : 2000 - (Date.now() - init_ts)); // get app directory puter.fs.stat({ @@ -401,8 +417,8 @@ $(document).on('click', '.delete-app', async function (e) { }, ]); }, - // make sure the modal was shown for at least 2 seconds - (Date.now() - init_ts) > 2000 ? 1 : 2000 - (Date.now() - init_ts)); + // make sure the modal was shown for at least 2 seconds + (Date.now() - init_ts) > 2000 ? 1 : 2000 - (Date.now() - init_ts)); }) } }) @@ -545,6 +561,13 @@ function generate_edit_app_section(app) { +

Misc

+
+ + +

When locked, the app cannot be deleted. This is useful to prevent accidental deletion of important apps.

+
+
@@ -938,6 +961,7 @@ $(document).on('click', '.edit-app-save-btn', async function (e) { }, window_resizable: $('#edit-app-window-resizable').is(":checked"), hide_titlebar: $('#edit-app-hide-titlebar').is(":checked"), + locked: $(`#edit-app-locked`).is(":checked") ?? false, }, filetypeAssociations: filetype_associations, }).then(async (app) => { @@ -994,8 +1018,22 @@ $(document).on('click', '.delete-app-settings', async function (e) { let app_name = $(this).attr('data-app-name'); let app_title = $(this).attr('data-app-title'); + // check if app is locked + const app_data = await puter.apps.get(app_name); + + if(app_data.metadata?.locked){ + puter.ui.alert(`${app_data.title} is locked and cannot be deleted.`, [ + { + label: 'Ok', + }, + ], { + type: 'warning', + }); + return; + } + // confirm delete - const alert_resp = await puter.ui.alert(`Are you sure you want to premanently delete "${html_encode(app_title)}"?`, + const alert_resp = await puter.ui.alert(`Are you sure you want to premanently delete ${html_encode(app_title)}?`, [ { label: 'Yes, delete permanently', @@ -1058,6 +1096,9 @@ $(document).on('click', '.back-to-main-btn', function (e) { $('#loading').show(); setTimeout(function () { puter.apps.list().then((apps_res) => { + // uncheck the select all checkbox + $('.select-all-apps').prop('checked', false); + $('#loading').hide(); apps = apps_res; if (apps.length > 0) { @@ -1186,7 +1227,7 @@ function generate_app_card(app) { // App info h += ``; // Icon - h += `
`; + h += `
`; // Info h += `
`; // Title @@ -1362,7 +1403,9 @@ function sort_apps() { sorted_apps.forEach(app => { $('#app-list-table > tbody').append(generate_app_card(app)); }); + count_apps(); + // show apps that match search_query and hide apps that don't if (search_query) { // show apps that match search_query and hide apps that don't @@ -1788,7 +1831,7 @@ $(document).on('click', '.add-app-to-desktop', function (e) { overwrite: false, appUID: app_uid, }).then(async (uploaded) => { - puter.ui.alert(`"${app_title}" shortcut has been added to your desktop.`, [ + puter.ui.alert(`${app_title} shortcut has been added to your desktop.`, [ { label: 'Ok', type: 'primary', @@ -1909,7 +1952,9 @@ $('.refresh-app-list').on('click', function (e) { apps.forEach(app => { $('#app-list-table > tbody').append(generate_app_card(app)); }); + count_apps(); + // preserve search query if (search_query) { // show apps that match search_query and hide apps that don't @@ -2011,7 +2056,7 @@ $(document).on('click', '.delete-apps-btn', async function (e) { if (resp === 'delete') { // disable delete button - $('.delete-apps-btn').addClass('disabled'); + // $('.delete-apps-btn').addClass('disabled'); // show 'deleting' modal $('.deleting-app-modal')?.get(0)?.showModal(); @@ -2025,6 +2070,43 @@ $(document).on('click', '.delete-apps-btn', async function (e) { const app_uid = $(app).attr('data-app-uid'); const app_name = $(app).attr('data-app-name'); + // get app + const app_data = await puter.apps.get(app_name); + + if(app_data.metadata?.locked){ + if(apps.length === 1){ + puter.ui.alert(`${app_data.title} is locked and cannot be deleted.`, [ + { + label: 'Ok', + }, + ], { + type: 'warning', + }); + + break; + } + + let resp = await puter.ui.alert(`${app_data.title} is locked and cannot be deleted.`, [ + { + label: 'Skip and Continue', + value: 'Continue', + type: 'primary' + }, + { + label: 'Cancel', + }, + ], { + type: 'warning', + }); + + if(resp === 'Cancel') + break; + else if(resp === 'Continue') + continue; + else + continue; + } + // delete app await puter.apps.delete(app_name) @@ -2065,13 +2147,13 @@ $(document).on('click', '.delete-apps-btn', async function (e) { // close 'deleting' modal setTimeout(() => { $('.deleting-app-modal')?.get(0)?.close(); - // uncheck all checkboxes - $('.app-checkbox').prop('checked', false); - // disable delete button - $('.delete-apps-btn').addClass('disabled'); - // reset the 'select all' checkbox - $('.select-all-apps').prop('indeterminate', false); - $('.select-all-apps').prop('checked', false); + if($('.app-checkbox:checked').length === 0){ + // disable delete button + $('.delete-apps-btn').addClass('disabled'); + // reset the 'select all' checkbox + $('.select-all-apps').prop('indeterminate', false); + $('.select-all-apps').prop('checked', false); + } }, (start_ts - Date.now()) > 500 ? 0 : 500); } }) diff --git a/src/gui/src/IPC.js b/src/gui/src/IPC.js index 9a08a50e..6e7234e4 100644 --- a/src/gui/src/IPC.js +++ b/src/gui/src/IPC.js @@ -156,7 +156,7 @@ window.addEventListener('message', async (event) => { //-------------------------------------------------------- else if(event.data.msg === 'ALERT' && event.data.message !== undefined){ const alert_resp = await UIAlert({ - message: html_encode(event.data.message), + message: event.data.message, buttons: event.data.buttons, type: event.data.options?.type, window_options: {