VulpesOS/gaia/apps/camera/js/controllers/controls.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

328 lines
7.8 KiB
JavaScript
Executable file

define(function(require, exports, module) {
'use strict';
/**
* Dependencies
*/
var debug = require('debug')('controller:controls');
var ControlsView = require('views/controls');
var bindAll = require('lib/bind-all');
/**
* Exports
*/
module.exports = function(app) { return new ControlsController(app); };
module.exports.ControlsController = ControlsController;
/**
* Initialize a new `ControlsController`
*
* @param {App} app
*/
function ControlsController(app) {
bindAll(this);
this.app = app;
this.activity = app.activity;
this.createView();
this.bindEvents();
debug('initialized');
}
/**
* Event bindings.
*
* @private
*/
ControlsController.prototype.bindEvents = function() {
this.app.settings.mode.on('change:selected', this.view.setMode);
this.app.settings.mode.on('change:options', this.configureMode);
// App
this.app.on('change:recording', this.onRecordingChange);
this.app.on('camera:shutter', this.captureHighlightOff);
this.app.on('camera:willchange', this.onCameraWillChange);
this.app.on('camera:configured', this.onCameraConfigured);
this.app.on('newthumbnail', this.onNewThumbnail);
this.app.once('loaded', this.onceAppLoaded);
this.app.on('busy', this.onCameraBusy);
this.app.on('localized', this.view.localize);
// View
this.view.on('modechanged', this.onViewModeChanged);
this.view.on('click:thumbnail', this.app.firer('preview'));
this.view.on('click:cancel', this.onCancelButtonClick);
this.view.on('click:capture', this.onCaptureClick);
// Timer
this.app.on('countdown:started', this.onCountdownStarted);
this.app.on('countdown:ended', this.onCountdownStopped);
// Settings
this.app.on('settings:opened', this.onSettingsOpened);
this.app.on('settings:closed', this.onSettingsClosed);
// Preview gallery
this.app.on('previewgallery:opened', this.view.hide);
this.app.on('previewgallery:closed', this.view.show);
debug('events bound');
};
/**
* Create and configure the view.
*
* @private
*/
ControlsController.prototype.createView = function() {
var initialMode = this.app.settings.mode.selected('key');
var cancellable = !!this.app.activity.pick;
// Create the view (test hook)
this.view = this.app.views.controls || new ControlsView();
// The gallery button should not
// be shown if an activity is pending
// or the application is in 'secure mode'.
this.view.set('cancel', cancellable);
this.view.setMode(initialMode);
// Disable view until camera
// 'ready' enables it.
this.view.disable();
// Put it in the DOM
this.view.appendTo(this.app.el);
debug('cancelable: %s', cancellable);
debug('mode: %s', initialMode);
};
/**
* Disables the switch if there is
* only one modes available.
*
* This is only the case if an activity
* indicated it only supports one mode,
* just 'picture' or 'video'.
*
* @private
*/
ControlsController.prototype.configureMode = function() {
var switchable = this.app.settings.mode.get('options').length > 1;
if (!switchable) { this.view.disable('switch'); }
};
/**
* Once the app is loaded, we can enable
* the controls. We also bind a listener
* that enabled the controls whenever
* the camera becomes 'ready' from
* hereon after.
*
* @private
*/
ControlsController.prototype.onceAppLoaded = function() {
this.app.on('ready', this.restore);
this.view.enable();
};
/**
* Keep capture button pressed and
* fire the `capture` event to allow
* the camera to repond.
*
* When the 'camera:shutter' event fires
* we remove the capture butter pressed
* state so that it times with the
* capture sound effect.
*
* @private
*/
ControlsController.prototype.onCaptureClick = function() {
this.captureHighlightOn();
this.app.emit('capture');
};
/**
* Prevent the mode switch from being changed
* by the user when we are in the process of
* configuring the camera.
*
* @private
*/
ControlsController.prototype.onCameraWillChange = function() {
this.view.suspendModeSwitch(true);
};
ControlsController.prototype.onCameraConfigured = function() {
this.view.suspendModeSwitch(false);
};
/**
* Set the recording attribute on
* the view to allow it to style
* accordingly.
*
* @param {Boolean} recording
* @private
*/
ControlsController.prototype.onRecordingChange = function(recording) {
this.view.set('recording', recording);
if (!recording) { this.onRecordingEnd(); }
// Update capture button label when recording changes.
this.view.setCaptureLabel(recording);
};
/**
* Remove the capture highlight,
* once recording has finished.
*
* @private
*/
ControlsController.prototype.onRecordingEnd = function() {
this.captureHighlightOff();
};
/**
* When the thumbnail changes, update it in the view.
* This method is triggered by the 'newthumbnail' event.
* That event is emitted by the preview gallery controller when the a new
* photo or video is added, or when the preview is closed and the first
* photo or video has changed (because of a file deletion).
*/
ControlsController.prototype.onNewThumbnail = function(thumbnailBlob) {
if (thumbnailBlob) {
this.view.setThumbnail(thumbnailBlob);
} else {
this.view.removeThumbnail();
}
};
/**
* Forces the capture button to
* look pressed while the countdown is
* counting down and hides controls.
*
* @private
*/
ControlsController.prototype.onCountdownStarted = function() {
this.captureHighlightOn();
this.view.set('countdown', 'active');
};
/**
* Forces the capture button to
* look unpressed when the countdown
* stops and shows controls.
*
* @private
*/
ControlsController.prototype.onCountdownStopped = function() {
this.captureHighlightOff();
this.view.set('countdown', 'inactive');
};
/**
* Make controls invisible to the screen reader since they are behind settings
* overlay.
*
* @private
*/
ControlsController.prototype.onSettingsOpened = function() {
this.view.setScreenReaderVisible(false);
};
/**
* Make controls visible to the screen reader again when settings are closed.
*
* @private
*/
ControlsController.prototype.onSettingsClosed = function() {
this.view.setScreenReaderVisible(true);
};
ControlsController.prototype.onCameraBusy = function() {
this.view.disable();
};
/**
* Restores the capture button to its
* unpressed state and re-enables buttons.
*
* @private
*/
ControlsController.prototype.restore = function() {
debug('restore');
this.captureHighlightOff();
this.view.enable();
};
/**
* Make the capture button
* appear pressed.
*
* @private
*/
ControlsController.prototype.captureHighlightOn = function() {
this.view.set('capture-active');
};
/**
* Remove the pressed apperance
* from the capture button.
*
* @private
*/
ControlsController.prototype.captureHighlightOff = function() {
this.view.unset('capture-active');
};
/**
* Switch to the next capture mode:
* 'picture' or 'video', when the
* mode is changed via the view.
*
* Them mode can be changed by either
* tapping or swiping the mode switch.
*
* @private
*/
ControlsController.prototype.onViewModeChanged = function() {
debug('view mode changed');
this.app.settings.mode.next();
};
ControlsController.prototype.onCancelButtonClick = function() {
this.app.emit('activitycanceled');
};
/**
* Open the gallery app when the
* gallery button is pressed.
*
* @private
*/
ControlsController.prototype.onGalleryButtonClick = function(event) {
event.stopPropagation();
var MozActivity = window.MozActivity;
// Can't launch the gallery if the lockscreen is locked.
// The button shouldn't even be visible in this case, but
// let's be really sure here.
if (this.app.inSecureMode) { return; }
// Launch the gallery with an activity
this.mozActivity = new MozActivity({
name: 'browse',
data: { type: 'photos' }
});
// Wait 2000ms before re-enabling the
// Gallery to be launched (Bug 957709)
this.view.disable();
setTimeout(this.view.enable, 2000);
};
});