Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
413 lines
13 KiB
JavaScript
Executable file
413 lines
13 KiB
JavaScript
Executable file
/*
|
|
* DevicePickerPanel is responsible for:
|
|
* - Render paired/found devices list in this panel.
|
|
* - Emit 'devicePicked' event with device address while a user click on a
|
|
* paired device.
|
|
* - Pair with the picked device while a user click on a found device.
|
|
* Emit 'devicePicked' event with device address until the picked device
|
|
* is pared.
|
|
* - Emit 'cancelSelection' event while a user click close button on the
|
|
* header for leaving.
|
|
*
|
|
* @module DevicePickerPanel
|
|
*/
|
|
define(function(require) {
|
|
'use strict';
|
|
|
|
var BtContext = require('modules/bluetooth/bluetooth_context');
|
|
var BtTemplateFactory = require('views/bt_template_factory');
|
|
var ListView = require('modules/mvvm/list_view');
|
|
|
|
var _debug = false;
|
|
var debug = function() {};
|
|
if (_debug) {
|
|
debug = function btdpp_debug(msg) {
|
|
console.log('--> [DevicePickerPanel]: ' + msg);
|
|
};
|
|
}
|
|
|
|
var DevicePickerPanel = {
|
|
/**
|
|
* A instance to maintain paired devices list view.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
* @type {Object}
|
|
*/
|
|
_pairedDevicesListView: null,
|
|
|
|
/**
|
|
* A instance to maintain found devices list view.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
* @type {Object}
|
|
*/
|
|
_foundDevicesListView: null,
|
|
|
|
/**
|
|
* Construct elements.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
* @type {Object}
|
|
*/
|
|
_elements: {
|
|
view: {
|
|
viewDevicePicker: document.querySelector('.devices-list-view')
|
|
},
|
|
header: {
|
|
headerActionClose: document.querySelector('.devices-list-header')
|
|
},
|
|
paired: {
|
|
pairedDevicesHeader: document.querySelector('.bluetooth-paired-title'),
|
|
pairedDevicesList: document.querySelector('.bluetooth-paired-devices')
|
|
},
|
|
found: {
|
|
foundDevicesHeader: document.querySelector('.bluetooth-found-title'),
|
|
foundDevicesList: document.querySelector('.bluetooth-devices')
|
|
},
|
|
search: {
|
|
searchingItem: document.querySelector('.bluetooth-searching'),
|
|
searchItem: document.querySelector('.bluetooth-search'),
|
|
searchButton: document.querySelector('.search-device')
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The object maintains listeners' callback per property name.
|
|
* Each listener would be called as following definition.
|
|
* 'devicePicked' - be called when device is picked and paired successfully.
|
|
* 'cancelSelection': - be called when user click on close button on header.
|
|
*
|
|
* @memberOf DevicePickerPanel
|
|
* @type {Object}
|
|
*/
|
|
_listeners: {
|
|
'devicePicked': [],
|
|
'cancelSelection': []
|
|
},
|
|
|
|
/**
|
|
* Default adapter of Bluetooth.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
* @type {Object} BluetoothAdapter
|
|
*/
|
|
_defaultAdapter: null,
|
|
|
|
/**
|
|
* The function init the paired/found devices list and search button.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_init: function btdpp__init() {
|
|
// Bind click event for header.
|
|
this._elements.header.headerActionClose.addEventListener('action',
|
|
this._onHeaderActionCloseClick.bind(this));
|
|
|
|
// Bind click event for search button.
|
|
this._elements.search.searchButton.addEventListener('click',
|
|
this._onSearchButtonClick.bind(this));
|
|
|
|
// Bind click event for paired device item.
|
|
var pairedDeviceTemplate =
|
|
BtTemplateFactory('paired', this._onPairedDeviceItemClick.bind(this));
|
|
|
|
// Create paired devices list view.
|
|
this._pairedDevicesListView =
|
|
ListView(this._elements.paired.pairedDevicesList,
|
|
BtContext.getPairedDevices(),
|
|
pairedDeviceTemplate);
|
|
|
|
// Bind click event for found device item.
|
|
var foundDeviceTemplate =
|
|
BtTemplateFactory('remote', this._onFoundDeviceItemClick.bind(this));
|
|
|
|
// Create found devices list view.
|
|
this._foundDevicesListView =
|
|
ListView(this._elements.found.foundDevicesList,
|
|
BtContext.getRemoteDevices(),
|
|
foundDeviceTemplate);
|
|
|
|
// Init items state.
|
|
this._initItemsState();
|
|
|
|
// search devices automatically while the panel is inited.
|
|
BtContext.startDiscovery().then(() => {
|
|
debug('_init(): startDiscovery successfully');
|
|
}, (reason) => {
|
|
debug('_init(): startDiscovery failed, ' +
|
|
'reason = ' + reason);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* The function init these elements which are displayed in this panel.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_initItemsState: function btdpp__initItemsState() {
|
|
// paired devices header
|
|
BtContext.observe('hasPairedDevice',
|
|
this._updatePairedDevicesHeader.bind(this));
|
|
this._updatePairedDevicesHeader(BtContext.hasPairedDevice);
|
|
|
|
// paired devices list
|
|
BtContext.observe('state', this._updatePairedDevicesList.bind(this));
|
|
this._updatePairedDevicesList(BtContext.state);
|
|
|
|
// found devices list
|
|
BtContext.observe('state', this._updateFoundDevicesList.bind(this));
|
|
this._updateFoundDevicesList(BtContext.state);
|
|
|
|
this._pairedDevicesListView.enabled = true;
|
|
this._foundDevicesListView.enabled = true;
|
|
|
|
// search
|
|
BtContext.observe('state', this._updateSearchItem.bind(this));
|
|
this._updateSearchItem(BtContext.state);
|
|
|
|
BtContext.observe('discovering', this._updateSearchingItem.bind(this));
|
|
this._updateSearchingItem(BtContext.discovering);
|
|
},
|
|
|
|
/**
|
|
* Start discovery devices while the search button is clicked.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_onHeaderActionCloseClick: function btdpp__onHeaderActionCloseClick() {
|
|
debug('_onHeaderActionCloseClick():');
|
|
// Emit 'cancelSelection' event to outer modules.
|
|
var event = {
|
|
type: 'cancelSelection'
|
|
};
|
|
this._emitEvent(event);
|
|
},
|
|
|
|
/**
|
|
* Start discovery devices while the search button is clicked.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_onSearchButtonClick: function btdpp__onSearchButtonClick() {
|
|
debug('_onSearchButtonClick():');
|
|
BtContext.startDiscovery().then(() => {
|
|
debug('_onSearchButtonClick(): startDiscovery successfully');
|
|
}, (reason) => {
|
|
debug('_onSearchButtonClick(): startDiscovery failed, ' +
|
|
'reason = ' + reason);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* While the paired device is clicked, emit event to outer modules with
|
|
* the device item.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_onPairedDeviceItemClick:
|
|
function btdpp__onPairedDeviceItemClick(deviceItem) {
|
|
debug('_onPairedDeviceItemClick(): deviceItem.address = ' +
|
|
deviceItem.address);
|
|
debug('_onPairedDeviceItemClick(): deviceItem.paired = ' +
|
|
deviceItem.paired);
|
|
// Emit 'devicePicked' event to outer modules with the device item.
|
|
var event = {
|
|
type: 'devicePicked',
|
|
detail: {
|
|
address: deviceItem.address
|
|
}
|
|
};
|
|
this._emitEvent(event);
|
|
},
|
|
|
|
/**
|
|
* Pair with the clicked device. While the device is paired successfully,
|
|
* emit event to outer modules with the device item.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_onFoundDeviceItemClick:
|
|
function btdpp__onFoundDeviceItemClick(deviceItem) {
|
|
debug('_onFoundDeviceItemClick(): deviceItem.address = ' +
|
|
deviceItem.address);
|
|
// Update device pairing status first.
|
|
deviceItem.paired = 'pairing';
|
|
// Pair with the remote device.
|
|
BtContext.pair(deviceItem.address).then(() => {
|
|
debug('_onFoundDeviceItemClick(): pair successfully');
|
|
// Emit 'devicePicked' event to outer modules with the
|
|
// paired device item.
|
|
var event = {
|
|
type: 'devicePicked',
|
|
detail: {
|
|
address: deviceItem.address
|
|
}
|
|
};
|
|
this._emitEvent(event);
|
|
}, (reason) => {
|
|
debug('_onFoundDeviceItemClick(): pair failed, ' +
|
|
'reason = ' + reason);
|
|
// Reset the paired status back to false,
|
|
// since the 'pairing' status is given in Gaia side.
|
|
deviceItem.paired = false;
|
|
// Show alert message while pair device failed.
|
|
this._alertPairFailedErrorMessage(reason);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show an alert dialog since the device is failed in pairing process.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_alertPairFailedErrorMessage:
|
|
function btdpp__alertPairFailedErrorMessage(errorReason) {
|
|
var _ = navigator.mozL10n.get;
|
|
var msg = _('error-pair-title'); // This is a default message.
|
|
if (errorReason === 'Repeated Attempts') {
|
|
msg = msg + '\n' + _('error-pair-toofast');
|
|
} else if (errorReason === 'Authentication Failed') {
|
|
msg = msg + '\n' + _('error-pair-pincode');
|
|
}
|
|
window.alert(msg);
|
|
},
|
|
|
|
/**
|
|
* A function to show/hide paired devices header.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_updatePairedDevicesHeader:
|
|
function btdpp__updatePairedDevicesHeader(hasPairedDevice) {
|
|
debug('_updatePairedDevicesHeader(): ' +
|
|
'callback from observe "hasPairedDevice" = ' + hasPairedDevice);
|
|
this._elements.paired.pairedDevicesHeader.hidden =
|
|
!(hasPairedDevice && (BtContext.state === 'enabled'));
|
|
},
|
|
|
|
/**
|
|
* A function to show/hide paired devices list.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_updatePairedDevicesList: function btdpp__updatePairedDevicesList(state) {
|
|
debug('_updatePairedDevicesList(): ' +
|
|
'callback from observe "state" = ' + state);
|
|
this._elements.paired.pairedDevicesHeader.hidden =
|
|
!((state === 'enabled') && (BtContext.hasPairedDevice));
|
|
this._elements.paired.pairedDevicesList.hidden = (state !== 'enabled');
|
|
},
|
|
|
|
/**
|
|
* A function to show/hide found devices list.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_updateFoundDevicesList: function btdpp__updateFoundDevicesList(state) {
|
|
debug('_updateFoundDevicesList(): ' +
|
|
'callback from observe "state" = ' + state);
|
|
this._elements.found.foundDevicesHeader.hidden = (state !== 'enabled');
|
|
this._elements.found.foundDevicesList.hidden = (state !== 'enabled');
|
|
},
|
|
|
|
/**
|
|
* A function to show/hide search item.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_updateSearchItem: function btdpp__updateSearchItem(state) {
|
|
debug('_updateSearchItem(): ' +
|
|
'callback from observe "state" = ' + state);
|
|
this._elements.search.searchItem.hidden = (state !== 'enabled');
|
|
},
|
|
|
|
/**
|
|
* A function to show/hide searching description item.
|
|
*
|
|
* @access private
|
|
* @memberOf DevicePickerPanel
|
|
*/
|
|
_updateSearchingItem: function btdpp__updateSearchingItem(discovering) {
|
|
debug('_updateSearchingItem(): ' +
|
|
'callback from observe "discovering" = ' + discovering);
|
|
this._elements.search.searchingItem.hidden = !discovering;
|
|
this._elements.search.searchButton.disabled = discovering;
|
|
},
|
|
|
|
/**
|
|
* A function to emit event to each registered listener by the input type.
|
|
*
|
|
* @memberOf DevicePickerPanel
|
|
* @param {Object} options
|
|
* @param {String} options.type - type of event name
|
|
* @param {Object} options.detail - the object pass to the listener
|
|
*/
|
|
_emitEvent: function btdpp__emitEvent(options) {
|
|
this._listeners[options.type].forEach(function(listener) {
|
|
listener(options);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* The method will provide event listener for outer modules to regist.
|
|
*
|
|
* @access public
|
|
* @memberOf DevicePickerPanel
|
|
* @param {String} eventName
|
|
* @param {Function} callback
|
|
*/
|
|
addEventListener: function btdpp_addEventListener(eventName, callback) {
|
|
if (callback && (this._listeners.hasOwnProperty(eventName))) {
|
|
this._listeners[eventName].push(callback);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The method will provide event listener for outer modules to un-regist.
|
|
*
|
|
* @access public
|
|
* @memberOf DevicePickerPanel
|
|
* @param {String} eventName
|
|
* @param {Function} callback
|
|
*/
|
|
removeEventListener:
|
|
function btdpp_removeEventListener(eventName, callback) {
|
|
if (callback && (this._listeners.hasOwnProperty(eventName))) {
|
|
var index = this._listeners[eventName].indexOf(callback);
|
|
if (index >= 0) {
|
|
this._listeners[eventName].splice(index, 1);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The setter will show/hide the device picker view for outer modules.
|
|
*
|
|
* @access public
|
|
* @memberOf DevicePickerPanel
|
|
* @param {Boolean} enabled
|
|
*/
|
|
set visible(enabled) {
|
|
// display device picker view
|
|
this._elements.view.viewDevicePicker.hidden = !enabled;
|
|
}
|
|
};
|
|
|
|
DevicePickerPanel._init();
|
|
return DevicePickerPanel;
|
|
});
|