diff --git a/apps/camera/js/app.js b/apps/camera/js/app.js index 21abeec2308b..b54bf92941c4 100644 --- a/apps/camera/js/app.js +++ b/apps/camera/js/app.js @@ -16,7 +16,6 @@ var ZoomBarView = require('views/zoom-bar'); var bindAll = require('lib/bind-all'); var debug = require('debug')('app'); var HudView = require('views/hud'); -var Pinch = require('lib/pinch'); var bind = require('lib/bind'); var model = require('model'); @@ -58,7 +57,8 @@ function App(options) { this.settings = options.settings; this.camera = options.camera; this.activity = {}; - + this.sounds = options.sounds; + this.Pinch = options.Pinch; // // If the system app is opening an attention screen (because // of an incoming call or an alarm, e.g.) and if we are @@ -201,10 +201,6 @@ App.prototype.bindEvents = function() { bind(this.win, 'beforeunload', this.onBeforeUnload); bind(this.el, 'click', this.onClick); - // Pinch - this.pinch = new Pinch(this.el); - this.pinch.on('pinchchanged', this.firer('pinchchanged')); - debug('events bound'); }; diff --git a/apps/camera/js/config/config.js b/apps/camera/js/config/config.js index 0fa1f0fb478e..88bc840f27ec 100644 --- a/apps/camera/js/config/config.js +++ b/apps/camera/js/config/config.js @@ -7,8 +7,8 @@ module.exports = { // shared/js/media/media_frame.js globals : { // The maximum picture size that camera is allowed to take - CONFIG_MAX_IMAGE_PIXEL_SIZE: 5242880, - CONFIG_MAX_SNAPSHOT_PIXEL_SIZE: 5242880, + CONFIG_MAX_IMAGE_PIXEL_SIZE: 3145728, // 3MP + CONFIG_MAX_SNAPSHOT_PIXEL_SIZE: 5242880, // 5MP // Size of the exif preview embeded in images taken by camera CONFIG_REQUIRED_EXIF_PREVIEW_WIDTH: 0, @@ -45,12 +45,6 @@ module.exports = { }, previewGallery: { - - // Flag for determining if the preview should limit the - // image size to the value of CONFIG_MAX_IMAGE_PIXEL_SIZE - // (enable for devices with limited memory) - limitMaxPreviewSize: false, - // Dimensions for thumbnail image (will automatically be // multiplied by the devicePixelRatio) thumbnailWidth: 54, diff --git a/apps/camera/js/controllers/camera.js b/apps/camera/js/controllers/camera.js index 4ec00ff52069..6f7b0b467c91 100644 --- a/apps/camera/js/controllers/camera.js +++ b/apps/camera/js/controllers/camera.js @@ -43,6 +43,7 @@ CameraController.prototype.bindEvents = function() { // Relaying camera events means other modules // don't have to depend directly on camera + camera.on('change:previewActive', this.app.firer('camera:previewactive')); camera.on('change:videoElapsed', app.firer('camera:recorderTimeUpdate')); camera.on('autofocuschanged', app.firer('camera:autofocuschanged')); camera.on('focusconfigured', app.firer('camera:focusconfigured')); @@ -62,10 +63,10 @@ CameraController.prototype.bindEvents = function() { // App app.on('viewfinder:focuspointchanged', this.onFocusPointChanged); - app.on('previewgallery:opened', this.onPreviewGalleryOpened); - app.on('previewgallery:closed', this.onPreviewGalleryClosed); app.on('change:batteryStatus', this.onBatteryStatusChange); app.on('settings:configured', this.onSettingsConfigured); + app.on('previewgallery:opened', this.shutdownCamera); + app.on('previewgallery:closed', this.onGalleryClosed); app.on('storage:changed', this.onStorageChanged); app.on('activity:pick', this.onPickActivity); app.on('timer:ended', this.capture); @@ -341,27 +342,22 @@ CameraController.prototype.onStorageChanged = function(state) { }; /** - * Resets the camera zoom and stops focus when the preview gallery - * is opened. + * Updates focus area when the user clicks on the viewfinder */ -CameraController.prototype.onPreviewGalleryOpened = function() { - this.camera.configureZoom(this.camera.previewSize()); - this.camera.stopFocus(); +CameraController.prototype.onFocusPointChanged = function(focusPoint) { + this.camera.updateFocusArea(focusPoint.area); }; -/** - * Resumes focus when the preview gallery - * is opened. - */ -CameraController.prototype.onPreviewGalleryClosed = function() { - this.camera.resumeFocus(); +CameraController.prototype.shutdownCamera = function() { + this.camera.stopRecording(); + this.camera.set('previewActive', false); + this.camera.set('focus', 'none'); + this.camera.release(); }; -/** - * Updates focus area when the user clicks on the viewfinder - */ -CameraController.prototype.onFocusPointChanged = function(focusPoint) { - this.camera.updateFocusArea(focusPoint.area); +CameraController.prototype.onGalleryClosed = function() { + this.app.showLoading(); + this.camera.load(this.app.clearLoading); }; -}); +}); \ No newline at end of file diff --git a/apps/camera/js/controllers/confirm.js b/apps/camera/js/controllers/confirm.js index 06298d5e425f..7259d19580b1 100644 --- a/apps/camera/js/controllers/confirm.js +++ b/apps/camera/js/controllers/confirm.js @@ -51,13 +51,8 @@ ConfirmController.prototype.renderView = function() { return; } - // Check whether the MediaFrame should limit the pixel size. - var maxPreviewSize = - this.settings.previewGallery.get('limitMaxPreviewSize') ? - window.CONFIG_MAX_IMAGE_PIXEL_SIZE : 0; - this.confirmView = new this.ConfirmView(); - this.confirmView.maxPreviewSize = maxPreviewSize; + this.confirmView.maxPreviewSize = window.CONFIG_MAX_IMAGE_PIXEL_SIZE; this.confirmView.render().appendTo(this.container); this.confirmView.on('click:select', this.onSelectMedia); diff --git a/apps/camera/js/controllers/preview-gallery.js b/apps/camera/js/controllers/preview-gallery.js index 5b513877b264..54a89b428cf4 100644 --- a/apps/camera/js/controllers/preview-gallery.js +++ b/apps/camera/js/controllers/preview-gallery.js @@ -63,10 +63,7 @@ PreviewGalleryController.prototype.openPreview = function() { return; } - // Check whether the MediaFrame should limit the pixel size. - var maxPreviewSize = - this.settings.previewGallery.get('limitMaxPreviewSize') ? - window.CONFIG_MAX_IMAGE_PIXEL_SIZE : 0; + var maxPreviewSize = window.CONFIG_MAX_IMAGE_PIXEL_SIZE; this.view = new PreviewGalleryView(); this.view.maxPreviewSize = maxPreviewSize; @@ -84,7 +81,6 @@ PreviewGalleryController.prototype.openPreview = function() { this.view.set('secure-mode', secureMode); this.view.open(); - this.app.set('previewGalleryOpen', true); this.previewItem(); this.app.emit('previewgallery:opened'); }; @@ -104,7 +100,6 @@ PreviewGalleryController.prototype.closePreview = function() { this.view = null; } - this.app.set('previewGalleryOpen', false); this.app.emit('previewgallery:closed'); }; @@ -336,7 +331,7 @@ PreviewGalleryController.prototype.previewItem = function() { * @param {Object} filepath */ PreviewGalleryController.prototype.onItemDeleted = function(data) { - + // Check if this event is being stopped such as in the case // of resizing an image for a share activity. if (this.stopItemDeletedEvent) { diff --git a/apps/camera/js/controllers/viewfinder.js b/apps/camera/js/controllers/viewfinder.js index 21ffdfd60340..c89c107cbacf 100644 --- a/apps/camera/js/controllers/viewfinder.js +++ b/apps/camera/js/controllers/viewfinder.js @@ -38,6 +38,7 @@ function ViewfinderController(app) { this.views.focus.appendTo(this.views.viewfinder.el); this.views.faces = new FacesView(); this.views.faces.appendTo(this.views.viewfinder.el); + this.pinch = new app.Pinch(app.el); this.bindEvents(); this.configure(); debug('initialized'); @@ -111,11 +112,14 @@ ViewfinderController.prototype.bindEvents = function() { this.app.on('camera:ready', this.views.viewfinder.enable); this.app.on('previewgallery:closed', this.onPreviewGalleryClosed); this.app.on('camera:configured', this.onCameraConfigured); - this.app.on('previewgallery:opened', this.stopStream); - this.app.on('settings:closed', this.configureGrid); - this.app.on('settings:opened', this.hideGrid); + this.app.on('previewgallery:opened', this.onGalleryOpened); + this.app.on('previewgallery:closed', this.onGalleryClosed); + this.app.on('camera:previewactive', this.onPreviewActive); + this.app.on('settings:closed', this.onSettingsClosed); + this.app.on('settings:opened', this.onSettingsOpened); this.app.on('hidden', this.stopStream); - this.app.on('pinchchanged', this.onPinchChanged); + + this.pinch.on('pinchchanged', this.onPinchChanged); }; /** @@ -126,7 +130,7 @@ ViewfinderController.prototype.bindEvents = function() { */ ViewfinderController.prototype.onCameraConfigured = function() { debug('configuring'); - this.startStream(); + this.loadStream(); this.configurePreview(); // BUG: We have to use a 300ms timeout here @@ -195,8 +199,7 @@ ViewfinderController.prototype.onPreviewGalleryClosed = function() { * * @private */ -ViewfinderController.prototype.startStream = function() { - if (this.app.get('previewGalleryOpen')) { return; } +ViewfinderController.prototype.loadStream = function() { this.camera.loadStreamInto(this.views.viewfinder.els.video); debug('stream started'); }; @@ -304,4 +307,32 @@ ViewfinderController.prototype.onViewfinderClicked = function(e) { this.app.emit('viewfinder:focuspointchanged', focusPoint); }; +ViewfinderController.prototype.onSettingsOpened = function() { + this.hideGrid(); + this.pinch.disable(); +}; + +ViewfinderController.prototype.onSettingsClosed = function() { + this.configureGrid(); + this.pinch.enable(); +}; + +ViewfinderController.prototype.onGalleryOpened = function() { + // Disables events when the gallery opens + this.viewfinder.disable(); + this.pinch.disable(); +}; + +ViewfinderController.prototype.onGalleryClosed = function() { + // Renables events when the gallery closes + this.viewfinder.enable(); + this.pinch.enable(); +}; + +ViewfinderController.prototype.onPreviewActive = function(active) { + if (!active) { + this.stopStream(); + } +}; + }); \ No newline at end of file diff --git a/apps/camera/js/lib/pinch.js b/apps/camera/js/lib/pinch.js index 8cc7b72341a6..58cf191cc988 100644 --- a/apps/camera/js/lib/pinch.js +++ b/apps/camera/js/lib/pinch.js @@ -48,8 +48,16 @@ Pinch.prototype.detach = function() { this.el = null; }; +Pinch.prototype.enable = function() { + this.disabled = false; +}; + +Pinch.prototype.disable = function() { + this.disabled = true; +}; + Pinch.prototype.onTouchStart = function(evt) { - if (evt.touches.length !== 2) { + if (evt.touches.length !== 2 || this.disabled) { return; } @@ -60,7 +68,7 @@ Pinch.prototype.onTouchStart = function(evt) { }; Pinch.prototype.onTouchMove = function(evt) { - if (!this.isPinching) { + if (!this.isPinching || this.disabled) { return; } @@ -75,7 +83,7 @@ Pinch.prototype.onTouchMove = function(evt) { }; Pinch.prototype.onTouchEnd = function(evt) { - if (!this.isPinching) { + if (!this.isPinching || this.disabled) { return; } diff --git a/apps/camera/js/main.js b/apps/camera/js/main.js index 5e38fb7f08a7..014addde623e 100644 --- a/apps/camera/js/main.js +++ b/apps/camera/js/main.js @@ -10,6 +10,7 @@ var GeoLocation = require('lib/geo-location'); var settingsData = require('config/config'); var settings = new Settings(settingsData); var Camera = require('lib/camera/camera'); +var Pinch = require('lib/pinch'); var App = require('app'); // Log dom-loaded to keep perf on our radar @@ -28,6 +29,7 @@ if (settingsData.globals) { var app = window.app = new App({ settings: settings, geolocation: new GeoLocation(), + Pinch: Pinch, el: document.body, doc: document, @@ -55,7 +57,7 @@ var app = window.app = new App({ confirm: 'controllers/confirm', battery: 'controllers/battery', sounds: 'controllers/sounds', - timer: 'controllers/timer', + timer: 'controllers/timer' } }); @@ -66,4 +68,4 @@ app.camera.load(); app.settings.fetch(); app.boot(); -}); \ No newline at end of file +}); diff --git a/apps/camera/style/viewfinder.css b/apps/camera/style/viewfinder.css index 8be2324ff8d9..5be6cb0adc88 100644 --- a/apps/camera/style/viewfinder.css +++ b/apps/camera/style/viewfinder.css @@ -25,8 +25,7 @@ /** * disabled */ - -.viewfinder[enabled=false] { +.viewfinder.disabled { pointer-events: none; } diff --git a/apps/camera/test/unit/controllers/camera_test.js b/apps/camera/test/unit/controllers/camera_test.js index 895440e3e071..36fd02129cc3 100644 --- a/apps/camera/test/unit/controllers/camera_test.js +++ b/apps/camera/test/unit/controllers/camera_test.js @@ -369,21 +369,6 @@ suite('controllers/camera', function() { }); }); - suite('CameraController#onPreviewGalleryOpened()', function() { - test('Should configure zoom and stop focus', function() { - this.controller.onPreviewGalleryOpened(); - assert.ok(this.camera.configureZoom.called); - assert.ok(this.camera.stopFocus.called); - }); - }); - - suite('CameraController#onPreviewGalleryClosed()', function() { - test('Should resume focus', function() { - this.controller.onPreviewGalleryClosed(); - assert.ok(this.camera.resumeFocus.called); - }); - }); - suite('CameraController#capture()', function() { test('Should not start countdown if now timer setting is set', function() { this.app.settings.timer.selected.returns(0); diff --git a/apps/camera/test/unit/controllers/preview-gallery_test.js b/apps/camera/test/unit/controllers/preview-gallery_test.js index 203fa3eb17f5..f6d1c41d3551 100644 --- a/apps/camera/test/unit/controllers/preview-gallery_test.js +++ b/apps/camera/test/unit/controllers/preview-gallery_test.js @@ -338,18 +338,24 @@ suite('controllers/preview-gallery', function() { this.controller.openPreview(); }); - test('Should set `previewGalleryOpen` to `true` on app', function() { - assert.isTrue(this.app.set.calledWith('previewGalleryOpen', true)); + test('Should call previewItem', function() { + assert.isTrue(this.controller.previewItem.called); }); }); suite('PreviewGalleryController#closePreview()', function() { setup(function() { + this.controller.view = new this.PreviewGalleryView(); + this.previewGalleryView = this.controller.view; + this.controller.view.close = sinon.spy(); + this.controller.view.destroy = sinon.spy(); this.controller.closePreview(); }); test('Should set `previewGalleryOpen` to `false` on app', function() { - assert.isTrue(this.app.set.calledWith('previewGalleryOpen', false)); + assert.isTrue(this.previewGalleryView.close.called); + assert.isTrue(this.previewGalleryView.destroy.called); + assert.isTrue(this.controller.view === null); }); }); diff --git a/apps/camera/test/unit/controllers/viewfinder_test.js b/apps/camera/test/unit/controllers/viewfinder_test.js index 66151bc1e14a..1d53d6dbc757 100644 --- a/apps/camera/test/unit/controllers/viewfinder_test.js +++ b/apps/camera/test/unit/controllers/viewfinder_test.js @@ -40,6 +40,8 @@ suite('controllers/viewfinder', function() { focusRing: sinon.createStubInstance(this.FocusRingView), faces: sinon.createStubInstance(this.FacesView) }; + this.app.Pinch = sinon.stub(); + this.app.Pinch.prototype.on = sinon.stub(); // Fake elements this.app.views.viewfinder.els = { video: {} }; @@ -68,23 +70,27 @@ suite('controllers/viewfinder', function() { suite('ViewfinderController()', function() { test('Should stop the stream when the PreviewGallery is opened', function() { - assert.isTrue(this.app.on.calledWith('previewgallery:opened', this.controller.stopStream)); + assert.isTrue(this.app.on.calledWith('previewgallery:opened', + this.controller.onGalleryOpened)); }); - test('Should listen when the PreviewGallery is closed', function() { - assert.isTrue(this.app.on.calledWith('previewgallery:closed')); + test('Should start the stream when the PreviewGallery is closed', function() { + assert.isTrue(this.app.on.calledWith('previewgallery:closed', + this.controller.onGalleryClosed)); }); - test('Should stop the stream when on app blur', function() { - assert.isTrue(this.app.on.calledWith('hidden', this.controller.stopStream)); + test('Should stop the stream preview is false', function() { + assert.isTrue(this.app.on.calledWith('camera:previewactive', this.controller.onPreviewActive)); }); test('Should hide the grid when the settings menu opened', function() { - assert.isTrue(this.app.on.calledWith('settings:opened', this.controller.hideGrid)); + assert.isTrue(this.app.on.calledWith('settings:opened', + this.controller.onSettingsOpened)); }); test('Should show the grid again when the settings menu is closed', function() { - assert.isTrue(this.app.on.calledWith('settings:closed', this.controller.configureGrid)); + assert.isTrue(this.app.on.calledWith('settings:closed', + this.controller.onSettingsClosed)); }); test('Should flash viewfinder shutter when camera shutter fires', function() { @@ -113,48 +119,13 @@ suite('controllers/viewfinder', function() { }); }); - suite('ViewfinderController#onPreviewGalleryClosed', function() { - setup(function() { - sinon.spy(this.controller, 'startStream'); - }); - - test('Should start the stream only if the app is visible', function() { - this.app.hidden = true; - this.controller.onPreviewGalleryClosed(); - assert.isFalse(this.controller.startStream.called); - - this.app.hidden = false; - this.controller.onPreviewGalleryClosed(); - assert.isTrue(this.controller.startStream.called); - }); - }); - - suite('ViewfinderController#onFacesDetected', function() { - setup(function() { - this.viewfinder.getSize.returns({ width: 800, height: 600}); - sinon.spy(this.faces, 'show'); - sinon.spy(this.faces, 'render'); - }); - - test('Should call render faces and show the faces view', function() { - this.controller.onFacesDetected([]); - assert.isTrue(this.controller.views.faces.show.called); - assert.isTrue(this.faces.render.called); - }); - }); - - suite('ViewfinderController#startStream()', function() { + suite('ViewfinderController#loadStream()', function() { test('Should load preview stream into viewfinder video element', function() { var video = this.viewfinder.els.video; - this.controller.startStream(); + this.controller.loadStream(); assert.isTrue(this.camera.loadStreamInto.calledWith(video)); }); - test('Should not `loadStreamInto` if preview-gallery is open', function() { - this.app.get.withArgs('previewGalleryOpen').returns(true); - this.controller.startStream(); - assert.isFalse(this.camera.loadStreamInto.called); - }); }); suite('ViewfinderController#configurePreview()', function() { diff --git a/apps/gallery/build/build.js b/apps/gallery/build/build.js index 147ed5ed3959..5a8928d9364c 100644 --- a/apps/gallery/build/build.js +++ b/apps/gallery/build/build.js @@ -58,6 +58,9 @@ GalleryAppBuilder.prototype.customizeMaximumImageSize = function(options) { // megapixel instead of 2 megapixel this.DEFAULT_VALUE.maxEditPixelSize = 800 * 600; } + else if (options.GAIA_MEMORY_PROFILE === '256') { + this.DEFAULT_VALUE.maxImagePixelSize = 3 * 1024 * 1024; + } var distDir = options.GAIA_DISTRIBUTION_DIR; var customize = JSON.parse(utils.getDistributionFileContent('gallery',