diff --git a/src/dev-center/js/apps.js b/src/dev-center/js/apps.js
index 2be245f5b..39dae8cb6 100644
--- a/src/dev-center/js/apps.js
+++ b/src/dev-center/js/apps.js
@@ -191,6 +191,9 @@ async function create_app (title, source_path = null, items = null) {
maximizeOnStart: false,
background: false,
dedupeName: true,
+ // New apps accept user feedback by default; developers can turn this
+ // off in the app's settings (the "User Feedback" toggle).
+ feedbackEnabled: true,
metadata: {
window_resizable: true,
fullpage_on_landing: true,
@@ -509,6 +512,12 @@ function generate_edit_app_section (app) {
Misc
+
+
+
+
When enabled, users can send you feedback about this app from within Puter. Feedback is delivered to your account's email address.
+
+
@@ -586,6 +595,7 @@ function trackOriginalValues () {
locked: $('#edit-app-locked').is(':checked'),
fullPageOnLanding: $('#edit-app-fullpage-on-landing').is(':checked'),
setTitleToFile: $('#edit-app-set-title-to-file').is(':checked'),
+ userFeedback: $('#edit-app-user-feedback').is(':checked'),
},
};
}
@@ -626,7 +636,8 @@ function hasChanges () {
$('#edit-app-hide-titlebar').is(':checked') !== originalValues.checkboxes.hideTitleBar ||
$('#edit-app-locked').is(':checked') !== originalValues.checkboxes.locked ||
$('#edit-app-fullpage-on-landing').is(':checked') !== originalValues.checkboxes.fullPageOnLanding ||
- $('#edit-app-set-title-to-file').is(':checked') !== originalValues.checkboxes.setTitleToFile
+ $('#edit-app-set-title-to-file').is(':checked') !== originalValues.checkboxes.setTitleToFile ||
+ $('#edit-app-user-feedback').is(':checked') !== originalValues.checkboxes.userFeedback
);
}
@@ -674,6 +685,7 @@ function resetToOriginalValues () {
$('#edit-app-locked').prop('checked', originalValues.checkboxes.locked);
$('#edit-app-fullpage-on-landing').prop('checked', originalValues.checkboxes.fullPageOnLanding);
$('#edit-app-set-title-to-file').prop('checked', originalValues.checkboxes.setTitleToFile);
+ $('#edit-app-user-feedback').prop('checked', originalValues.checkboxes.userFeedback);
if ( originalValues.icon ) {
$('#edit-app-icon').css('background-image', `url(${originalValues.icon})`);
@@ -1284,6 +1296,7 @@ async function saveEditedApp (mode) {
description: description,
maximizeOnStart: $('#edit-app-maximize-on-start').is(':checked'),
background: $('#edit-app-background').is(':checked'),
+ feedbackEnabled: $('#edit-app-user-feedback').is(':checked'),
metadata: {
fullpage_on_landing: $('#edit-app-fullpage-on-landing').is(':checked'),
social_image: socialImageUrl,
diff --git a/src/puter-js/tests/api/suites/apps.suite.ts b/src/puter-js/tests/api/suites/apps.suite.ts
index 12aa6a805..8ee2e0e26 100644
--- a/src/puter-js/tests/api/suites/apps.suite.ts
+++ b/src/puter-js/tests/api/suites/apps.suite.ts
@@ -144,6 +144,28 @@ export default suite('apps', {
t.assert.equal(updated.description, 'New description');
},
+ 'feedbackEnabled round-trips on create and survives an unrelated update':
+ async (t) => {
+ // Mirrors Dev Center: create with feedback on, then a Save-style
+ // update that omits feedbackEnabled must not clear it.
+ const created = await t.puter.apps.create({
+ name: 'apps-suite-feedback',
+ indexURL: 'https://example.com/feedback',
+ feedbackEnabled: true,
+ });
+ t.assert.equal(Boolean(created.feedback_enabled), true);
+
+ const updated = await t.puter.apps.update('apps-suite-feedback', {
+ title: 'Feedback App',
+ });
+ t.assert.equal(Boolean(updated.feedback_enabled), true);
+
+ const disabled = await t.puter.apps.update('apps-suite-feedback', {
+ feedbackEnabled: false,
+ });
+ t.assert.equal(Boolean(disabled.feedback_enabled), false);
+ },
+
'get of an unknown app rejects': async (t) => {
await t.assert.rejects(
() => t.puter.apps.get('apps-suite-does-not-exist'),