Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #17938 from gasolin/issue-973445
Browse files Browse the repository at this point in the history
Bug 973445 - [settings] refactor Sound panel with AMD pattern, r=arthur
  • Loading branch information
gasolin committed Apr 22, 2014
2 parents a87266f + 33f5497 commit 0ea19c0
Show file tree
Hide file tree
Showing 9 changed files with 430 additions and 153 deletions.
2 changes: 1 addition & 1 deletion apps/settings/README.md
Expand Up @@ -180,7 +180,7 @@ If the old module called Settings.mozSettings, Use SettingsCache.getString() ins
```js
var SettingsCache = require('modules/settings_cache');
...
SettingsCache.getSettings(function(result){
SettingsCache.getSettings(function(result) {
var onlineSupportTitle = result['support.onlinesupport.title'];
...
});
Expand Down
3 changes: 1 addition & 2 deletions apps/settings/elements/sound.html
Expand Up @@ -106,8 +106,7 @@ <h2 data-l10n-id="other-sounds">Other Sounds</h2>
</ul>
</div>

<script src="shared/js/omadrm/fl.js"></script>
<script src="js/sound.js"></script>
<panel data-path="panels/sound/panel"></panel>

</template>
</element>
16 changes: 13 additions & 3 deletions apps/settings/js/config/require.js
Expand Up @@ -9,15 +9,18 @@ require.config({
'settings': {
exports: 'Settings'
},
'shared/keyboard_helper': {
exports: 'KeyboardHelper'
},
'shared/lazy_loader': {
exports: 'LazyLoader'
},
'shared/omadrm/fl': {
exports: 'ForwardLock'
},
'shared/screen_layout': {
exports: 'ScreenLayout'
},
'shared/keyboard_helper': {
exports: 'KeyboardHelper'
},
'shared/settings_listener': {
exports: 'SettingsListener'
}
Expand All @@ -44,6 +47,13 @@ require.config({
{
name: 'panels/help/panel',
exclude: ['main']
},
{
name: 'panels/sound/panel',
exclude: [
'main',
'shared/settings_listener'
]
}
]
});
29 changes: 29 additions & 0 deletions apps/settings/js/panels/sound/panel.js
@@ -0,0 +1,29 @@
/**
* Used to show Personalization/Sound panel
*/
define(function(require) {
'use strict';

var SettingsPanel = require('modules/settings_panel');
var Sound = require('panels/sound/sound');

return function ctor_sound_panel() {
var sound = Sound();

return SettingsPanel({
onInit: function(panel) {
var elements = {
toneSelector: panel.querySelector('#touch-tone-selector'),
alertTone: panel.querySelector('#alert-tone-selection'),
ringTone: panel.querySelector('#ring-tone-selection'),
ringer: panel.querySelector('#ringer')
};

sound.init(elements);
},
onUninit: function() {
sound.uninit();
}
});
};
});
186 changes: 186 additions & 0 deletions apps/settings/js/panels/sound/sound.js
@@ -0,0 +1,186 @@
/* global getSupportedNetworkInfo, URL, MozActivity */
/**
* Handle sound panel functionality
*/
define(function(require) {
'use strict';

var ForwardLock = require('shared/omadrm/fl');
var SettingsListener = require('shared/settings_listener');

var Sound = function() {
this.elements = null;
this.tones = null;
};

Sound.prototype = {
/**
* initialization
*/
init: function sound_init(elements) {
this.elements = elements;

if (window.navigator.mozMobileConnections) {
var mobileConnections = window.navigator.mozMobileConnections;
// Show the touch tone selector if and only if we're on a CDMA network
var toneSelector = this.elements.toneSelector;
Array.prototype.forEach.call(mobileConnections,
function(mobileConnection) {
getSupportedNetworkInfo(mobileConnection, function(result) {
toneSelector.hidden = toneSelector.hidden && !result.cdma;
});
});
}

// initialize the ring tone and alert tone menus.
this._configureTones();
this._handleTones();
},

uninit: function sound_uninit() {
this.elements = null;
this.tones = null;
},

_configureTones: function sound_configureTones() {
/**
* This array has one element for each selectable tone that appears in the
* "Tones" section of ../elements/sound.html.
*/
this.tones = [{
pickType: 'alerttone',
settingsKey: 'notification.ringtone',
allowNone: true, // Allow "None" as a choice for alert tones.
button: this.elements.alertTone
}];

// If we're a telephone, then show the section for ringtones, too.
if (navigator.mozTelephony) {
this.tones.push({
pickType: 'ringtone',
settingsKey: 'dialer.ringtone',
allowNone: false, // The ringer must always have an actual sound.
button: this.elements.ringTone
});
this.elements.ringer.hidden = false;
}
},

_handleTones: function sound_handleTones() {
var _ = navigator.mozL10n.get;
var self = this;

// For each kind of tone, hook up the button that will allow the user
// to select a sound for that kind of tone.
this.tones.forEach(function(tone) {
var namekey = tone.settingsKey + '.name';
// The button looks like a select element. By default it just reads
// "change". But we want it to display the name of the current tone.
// So we look up that name in the settings database.
SettingsListener.observe(namekey, '', function(tonename) {
tone.button.textContent = tonename || _('change');
});

// When the user clicks the button, we launch an activity that lets
// the user select new ringtone.
tone.button.onclick = function() {
/**
* Before we can start the Pick activity, we need to know if there
* is locked content on the phone because we don't want the user to
* see "Purchased Media" as a choice if there isn't any purchased
* media on the phone. The ForwardLock secret key is not generated
* until it is needed, so we can use its existance to
* determine whether to show the Purchased Media app.
*/
ForwardLock.getKey(function(secret) {
var activity = new MozActivity({
name: 'pick',
data: {
type: tone.pickType,
allowNone: tone.allowNone,
// If we have a secret then there is locked content on the phone
// so include it as a choice for the user
includeLocked: (secret !== null)
}
});

activity.onsuccess = function() {
var blob = activity.result.blob; // The returned ringtone sound
var name = activity.result.name; // The name of this ringtone

if (!blob) {
if (tone.allowNone) {
// If we allow a null blob, then everything is okay
self._setRingtone(blob, name, tone.settingsKey);
} else {
// Otherwise this is an error and we should not change the
// current setting. (The ringtones app should never return
// a null blob if allowNone is false, but other apps might.)
alert(_('unplayable-ringtone'));
}
return;
}

// If we got a locked ringtone, we have to unlock it first
if (blob.type.split('/')[1] === ForwardLock.mimeSubtype) {
ForwardLock.unlockBlob(secret, blob, function(unlocked) {
self._checkRingtone(unlocked, name, tone);
});
} else { // Otherwise we can just use the blob directly.
self._checkRingtone(blob, name, tone);
}
};
});
};
});
},
/**
* Make sure that the blob we got from the activity is actually
* a playable audio file. It would be very bad to set an corrupt
* blob as a ringtone because then the phone wouldn't ring!
*/
_checkRingtone: function sound_checkRingtone(blob, name, tone) {
var _ = navigator.mozL10n.get;
var oldRingtoneName = tone.button.textContent;
tone.button.textContent = _('savingringtone');

var player = new Audio();
player.preload = 'metadata';
player.src = URL.createObjectURL(blob);
player.oncanplay = function() {
release();
// this will update the button text
this._setRingtone(blob, name, tone.settingsKey);
}.bind(this);
player.onerror = function() {
release();
tone.button.textContent = oldRingtoneName;
alert(_('unplayable-ringtone'));
};

function release() {
URL.revokeObjectURL(player.src);
player.removeAttribute('src');
player.load();
}
},
/*
* Save the sound in the settings db so that other apps can
* use it.
* Also save the sound name in the db so we can display it in the future.
* And update the button text to the new name now.
*/
_setRingtone: function sound_setRingtone(blob, name, settingsKey) {
// Update the settings database. This will cause the button
// text to change as well because of the SettingsListener above.
var values = {};
values[settingsKey] = blob;
values[settingsKey + '.name'] = name || '';
navigator.mozSettings.createLock().set(values);
}
};

return function ctor_sound() {
return new Sound();
};
});

0 comments on commit 0ea19c0

Please sign in to comment.