diff --git a/apps/homescreen/js/app.js b/apps/homescreen/js/app.js index 9d421b9a3312..ce9f50149036 100644 --- a/apps/homescreen/js/app.js +++ b/apps/homescreen/js/app.js @@ -1,6 +1,5 @@ /* global MozActivity, HomeMetadata, Datastore, LazyLoader, FirstRun, IconsHelper, Settings */ -/* jshint nonew: false */ 'use strict'; (function(exports) { @@ -742,10 +741,20 @@ } navigator.mozApps.mgmt.uninstall(this.selectedIcon.app); } else if (this.selectedIcon.bookmark) { - new MozActivity({ + var remove = new MozActivity({ name: 'remove-bookmark', data: { type: 'url', url: this.selectedIcon.bookmark.id } }); + + // Re-enter edit mode because the activity will hide the document, + // which exits edit mode + var icon = this.selectedIcon; + remove.onsuccess = () => { + this.enterEditMode(null); + }; + remove.onerror = () => { + this.enterEditMode(icon); + }; } }, @@ -754,10 +763,17 @@ return; } - new MozActivity({ + var rename = new MozActivity({ name: 'save-bookmark', data: { type: 'url', url: this.selectedIcon.bookmark.id } }); + + // Re-enter edit mode because the activity will hide the document, + // which exits edit mode + var icon = this.selectedIcon; + rename.onsuccess = rename.onerror = () => { + this.enterEditMode(icon); + }; }, iconIsEditable: function(icon) { @@ -802,10 +818,10 @@ }, enterEditMode: function(icon) { - console.debug('Entering edit mode on ' + icon.name); + console.debug('Entering edit mode on ' + (icon ? icon.name : 'no icon')); this.updateSelectedIcon(icon); - if (this.editMode || !this.selectedIcon) { + if (this.editMode) { return; } diff --git a/apps/homescreen/js/pages.js b/apps/homescreen/js/pages.js index 065f005c5a80..5e6e61a0f176 100644 --- a/apps/homescreen/js/pages.js +++ b/apps/homescreen/js/pages.js @@ -183,6 +183,10 @@ }, exitEditMode: function() { + if (!this.editMode) { + return; + } + this.editMode = false; document.body.classList.remove('edit-mode'); this.remove.classList.remove('active'); @@ -198,9 +202,7 @@ } this.pages.removeChild(card, () => { if (!this.empty && this.pages.children.length === 0) { - if (this.editMode) { - this.exitEditMode(); - } + this.exitEditMode(); this.empty = true; this.panel.classList.add('empty'); } diff --git a/apps/homescreen/js/window.js b/apps/homescreen/js/window.js index 56af1f1598df..4d5b156410ca 100644 --- a/apps/homescreen/js/window.js +++ b/apps/homescreen/js/window.js @@ -29,6 +29,7 @@ this.panels.addEventListener('scroll', this); window.addEventListener('hashchange', this, true); window.addEventListener('localized', this); + document.addEventListener('visibilitychange', this); // Update the panel indicator this.updatePanelIndicator(); @@ -156,6 +157,15 @@ case 'localized': this.updatePanelIndicator(); return; + + // Exit edit mode if the user switches away from the home screen (e.g. + // by locking the phone). + case 'visibilitychange': + if (document.hidden) { + this.apps.exitEditMode(); + this.pages.exitEditMode(); + } + return; } } }; diff --git a/apps/homescreen/test/unit/app_test.js b/apps/homescreen/test/unit/app_test.js index 3c58567951d2..ef698b17c5d1 100644 --- a/apps/homescreen/test/unit/app_test.js +++ b/apps/homescreen/test/unit/app_test.js @@ -741,15 +741,17 @@ suite('Homescreen app', () => { }); suite('App#removeSelectedIcon()', () => { - var uninstallStub; + var uninstallStub, clock; setup(() => { MockMozActivity.mSetup(); uninstallStub = sinon.stub(navigator.mozApps.mgmt, 'uninstall'); + clock = sinon.useFakeTimers(); }); teardown(() => { MockMozActivity.mTeardown(); uninstallStub.restore(); + clock.restore(); }); test('does nothing with no selected icon', () => { @@ -780,15 +782,30 @@ suite('Homescreen app', () => { assert.equal(MockMozActivity.calls[0].data.url, app.selectedIcon.bookmark.id); }); + + test('re-enters edit mode when removing bookmarks', () => { + var enterEditModeStub = sinon.stub(app, 'enterEditMode'); + app.selectedIcon = { bookmark: { id: 'abc' } }; + app.removeSelectedIcon(); + + MockMozActivity.mTriggerOnError(); + assert.isTrue(enterEditModeStub.calledWith(app.selectedIcon)); + + clock.tick(50); + assert.isTrue(enterEditModeStub.calledWith(null)); + }); }); suite('App#renameSelectedIcon()', () => { + var clock; setup(() => { MockMozActivity.mSetup(); + clock = sinon.useFakeTimers(); }); teardown(() => { MockMozActivity.mTeardown(); + clock.restore(); }); test('does nothing with no selected icon', () => { @@ -812,6 +829,18 @@ suite('Homescreen app', () => { assert.equal(MockMozActivity.calls[0].data.url, app.selectedIcon.bookmark.id); }); + + test('re-enters edit mode', () => { + var enterEditModeStub = sinon.stub(app, 'enterEditMode'); + app.selectedIcon = { bookmark: { id: 'abc' } }; + app.renameSelectedIcon(); + + MockMozActivity.mTriggerOnError(); + assert.isTrue(enterEditModeStub.calledWith(app.selectedIcon)); + + clock.tick(50); + assert.isTrue(enterEditModeStub.calledWith(app.selectedIcon)); + }); }); suite('App#iconIsEditable()', () => { diff --git a/apps/homescreen/test/unit/window_test.js b/apps/homescreen/test/unit/window_test.js index 0c0290920d06..7cfb06fb40ec 100644 --- a/apps/homescreen/test/unit/window_test.js +++ b/apps/homescreen/test/unit/window_test.js @@ -300,5 +300,29 @@ suite('AppWindow', () => { exitEditModeStub.restore(); }); }); + + suite('visibilitychange', () => { + var appsExitEditModeStub, pagesExitEditModeStub; + setup(() => { + appsExitEditModeStub = sinon.stub(appWindow.apps, 'exitEditMode'); + pagesExitEditModeStub = sinon.stub(appWindow.pages, 'exitEditMode'); + Object.defineProperty(document, 'hidden', { + value: true, + configurable: true + }); + }); + + teardown(() => { + appsExitEditModeStub.restore(); + pagesExitEditModeStub.restore(); + delete document.hidden; + }); + + test('should exit edit mode', () => { + appWindow.handleEvent(new CustomEvent('visibilitychange')); + assert.isTrue(appsExitEditModeStub.called); + assert.isTrue(pagesExitEditModeStub.called); + }); + }); }); });