define('application/components/recordings', [
'rofl/widgets/component',
'rofl/widgets/verticallist',
'application/widgets/recordings/filters',
'application/widgets/recordings/grid',
'application/widgets/clock',
'rofl/lib/utils',
'rofl/widgets/label',
'rofl/lib/l10n',
'antie/runtimecontext',
'application/managers/recording',
'rofl/events/keyevent',
'application/widgets/infoblock',
'rofl/lib/promise',
'rofl/widgets/container',
'rofl/analytics/web/google',
'application/managers/halo'
], function (
Component,
VerticalList,
Filters,
Grid,
Clock,
Utils,
Label,
L10N,
RuntimeContext,
RecordingManager,
KeyEvent,
InfoBlock,
Promise,
Container,
GoogleAnalytics,
HaloManager
) {
'use strict';
var application = RuntimeContext.getCurrentApplication(),
layout = application.getLayout(),
defaultGridPosition = layout.recordings.grid.default,
device = RuntimeContext.getDevice(),
l10n = L10N.getInstance(),
GA = GoogleAnalytics.getInstance(),
infoblockConfig = {
id: 'back-on-top-block',
text: l10n.get('infoblock'),
classname: ['icon', 'icon-back-v2'],
position: 'right'
},
recordingManager = RecordingManager.getInstance();
return Component.extend({
/**
* Initialises the component.
*/
init: function init () {
init.base.call(this, 'recordings');
this.addClass('fullscreen');
this._build();
this._setBindings();
},
/**
* Builds the component.
*
* @private
*/
_build: function () {
var list = this._list = new VerticalList(),
filters = this._filters = new Filters(),
grid = this._grid = new Grid(),
infoBlock = this._infoBlock = new InfoBlock(infoblockConfig),
clock = new Clock(),
title = new Label({ text: l10n.get('recordings.title'), classNames: ['top-title'] }),
branding = this._branding = new Container();
branding.addClass('page-branding');
infoBlock.addClass('info-block');
clock.addClass('header-clock');
list.appendChildWidget(filters);
list.appendChildWidget(grid);
branding.appendChildWidget(title);
this.appendChildWidget(branding);
this.appendChildWidget(clock);
this.appendChildWidget(list);
this.appendChildWidget(infoBlock);
},
/**
* BeforeShow event.
*/
onBeforeShow: function () {
this._setEventListeners();
this._filters.setSelectedItem(this._filters.getChildWidgetByIndex(0));
GA.onPageView('recordings');
this._reload = true;
application.showLoader();
this._reset();
this._loadData({
current: true
});
HaloManager.getInstance()
.getServiceMessage()
.then(function (r) {
if (r) {
application.route('service');
}
});
},
/**
* BeforeHide event.
*/
onBeforeHide: function () {
this._removeEventListeners();
},
/**
* Loads the data based on the options.
*
* @param {Object} options - The options.
* @private
*/
_loadData: function (options) {
var promise;
this._loadOptions = options;
if (options.current) {
promise = this._loadCurrentRecordings();
} else if (options.planned) {
promise = this._loadUpcomingRecordings();
}
promise
.then(Utils.bind(this._setData, this, options, true))
['catch'](Utils.bind(this._onError, this));
},
/**
* Loads the current recordings.
*
* @returns {Promise} - Promise resolving with the recordings.
* @private
*/
_loadCurrentRecordings: function () {
return recordingManager.getCurrentSeriesRecordings({
forceReload: this._reload
});
},
/**
* Loads the upcoming recordings.
*
* @returns {Promise} - Promise resolving with the recordings.
* @private
*/
_loadUpcomingRecordings: function () {
return recordingManager.getPlannedSeriesRecordings();
},
/**
* Sets the data to the grid.
*
* @param {Object} options - The load options.
* @param {boolean} shouldFocus - True if the grid should receive focus.
* @param {Object} data - The data.
* @returns {Promise} - The promise.
* @private
*/
_setData: function (options, shouldFocus, data) {
var title = '';
return new Promise(Utils.bind(function (resolve) {
if (!data.length) {
if (options.current) {
title = l10n.get('recordings.noresults.current');
} else {
title = l10n.get('recordings.noresults.planned');
}
}
this._reload = false;
this._grid.setDataItem({
items: data,
title: title
}, shouldFocus);
if (shouldFocus) {
if (data.length) {
this._grid.focus();
} else {
this._filters.focus();
}
}
application.hideLoader();
resolve();
}, this));
},
/**
* Gets executed when an error triggers.
*
* @private
*/
_onError: function () {
application.route('error', {
type: 'fullscreen',
title: L10N.getInstance().get('errors.cannot_load_page'),
button: {
id: 'error-close-button',
label: L10N.getInstance().get('errors.close')
},
imgUrl: 'src/assets/images/error-icon.png'
});
},
/**
* Sets the bindings.
*
* @private
*/
_setBindings: function () {
this._onSelectBound = Utils.bind(this._onSelect, this);
this._onKeyDownBound = Utils.bind(this._onKeyDown, this);
this._onSelectedItemChangeBound = Utils.bind(this._onSelectedItemChange, this);
this._onRecordChangeBound = Utils.bind(this._onRecordChange, this);
},
/**
* Sets the event listeners.
*
* @private
*/
_setEventListeners: function () {
this.addEventListener('selecteditemchange', this._onSelectedItemChangeBound);
application.addEventListener('$record', this._onRecordChangeBound);
this._setSelectListener();
},
/**
* Removes the event listeners.
*
* @private
*/
_removeEventListeners: function () {
this.removeEventListener('selecteditemchange', this._onSelectedItemChangeBound);
application.removeEventListener('$record', this._onRecordChangeBound);
this._removeSelectListener();
},
/**
* Removes the select listener.
*
* @private
*/
_setSelectListener: function () {
if (this._listening) {
return;
}
this._listening = true;
this.addEventListener('select', this._onSelectBound);
this.addEventListener('keydown', this._onKeyDownBound);
},
/**
* Removes the select listener.
*
* @private
*/
_removeSelectListener: function () {
if (!this._listening) {
return;
}
this._listening = false;
this.removeEventListener('select', this._onSelectBound);
this.removeEventListener('keydown', this._onKeyDownBound);
},
/**
* Ahows asset detail modal.
*
* @param {Object} data - Asset.
* @private
*/
_showAssetDetail: function (data) {
application.route('epgdetail', {
callback: Utils.bind(this.focus, this),
data: data,
callingPage: 'recordings',
series: Utils.isFunction(data.getItems)
});
},
/**
* Select listener.
*
* @param {Object} e - The event data.
* @private
*/
_onSelect: function (e) {
var target = e.target,
data;
switch (target.id) {
case 'current-recordings':
this._filters.setSelectedItem(target);
this._loadData({
current: true
});
break;
case 'planned-recordings':
this._filters.setSelectedItem(target);
this._loadData({
planned: true
});
break;
case 'back-on-top-block':
this._grid.alignToFirstItem();
break;
default:
if (target.hasClass('asset')) {
data = target.getDataItem().item;
if (target.isLocked()) {
this._removeSelectListener();
application.route('parentalpin', {
successCallback: Utils.bind(function () {
this._showAssetDetail(data);
this._unlockAssets();
this._setSelectListener();
}, this),
escapeCallback: Utils.bind(function () {
target.focus();
this._setSelectListener();
}, this),
errorCallback: Utils.bind(function () {
target.focus();
this._setSelectListener();
}, this)
});
return;
}
this._showAssetDetail(data);
}
}
},
/**
* Unlock the assets.
*
* @private
*/
_unlockAssets: function () {
var rows = this._list.getChildWidgetByIndex(1).getList().getChildWidgets(),
assets;
Utils.each(rows, function (row) {
assets = row.getChildWidgets();
Utils.each(assets, function (asset) {
asset.unlock();
});
});
},
/**
* Selected item change event.
*
* @param {Object} e - The event data.
* @private
*/
_onSelectedItemChange: function (e) {
var infoBlock = this._infoBlock;
if (e.target.hasClass('skeleton')) {
if (e.index) {
if (!infoBlock.isVisible()) {
infoBlock.show();
}
} else {
if (infoBlock.isVisible()) {
infoBlock.hide();
}
}
}
},
/**
* KeyDown Event listener.
*
* @param {Object} e - The event data.
* @private
*/
_onKeyDown: function (e) {
var samsungChannelKey = this._handleChannelKey(e);
if (e.keyCode !== KeyEvent.VK_GUIDE &&
e.keyCode !== KeyEvent.VK_INFO &&
e.keyCode !== KeyEvent.VK_LIST &&
!samsungChannelKey) {
e.preventDefault();
e.stopPropagation();
}
if (e.keyCode === KeyEvent.VK_LEFT) {
application.focusMenu('main');
} else if (e.keyCode === KeyEvent.VK_BACK) {
this._onBack();
}
},
/**
* Determines if Samsung's channel key will be handled by the main app or the component.
*
* @param {Object} e - The keyEvent data.
* @returns {boolean} - True if the channel key will be handled by main app instead of component.
*/
_handleChannelKey: function (e) {
var deviceBrand = device.getBrand();
return (e.keyCode === KeyEvent.VK_CHANNEL_UP || e.keyCode === KeyEvent.VK_CHANNEL_DOWN) &&
deviceBrand === 'samsung';
},
/**
* Executes when the back button is used.
*
* @private
*/
_onBack: function () {
var gridItemsCount = this._grid.getList().getChildWidgetCount();
if (gridItemsCount && this._grid.getActiveChildIndex() !== 0) {
this._grid.alignToFirstItem();
} else {
application.focusMenu('main');
}
},
/**
* Resets the view.
*
* @private
*/
_reset: function () {
device.moveElementTo({
el: this._grid.outputElement,
skipAnim: true,
to: {
top: defaultGridPosition.top,
left: defaultGridPosition.left
}
});
this._filters.setActiveChildIndex(0);
this._infoBlock.hide({skipAnim: true});
},
/**
* Gets executed when a recording status changes.
*
* @param {Object} e - The event.
* @private
*/
_onRecordChange: function (e) {
if (e.deleted) {
this._reloadDisplay();
}
},
/**
* Reloads the component.
*
* @private
*/
_reloadDisplay: function () {
var grid = this._grid,
activeRowIndex = grid.getActiveChildIndex(),
activeItemIndex = grid.getActiveItemIndex(),
gridList = grid.getList().getMask().getWidgetStrip(),
self = this,
activeRow,
promise,
rowChildWidgetCount;
if (this._loadOptions.current) {
promise = this._loadCurrentRecordings();
} else {
promise = this._loadUpcomingRecordings();
}
promise
.then(Utils.bind(this._setData, this, this._loadOptions, false))
.then(function () {
rowChildWidgetCount = grid.getRowChildWidgetCount();
if (rowChildWidgetCount > 0) {
if (rowChildWidgetCount - 1 < activeRowIndex) {
activeItemIndex = 3; // The last index.
}
// Check if the active row exists or should move to the previous row.
if (!gridList.getChildWidgetByIndex(activeRowIndex)) {
activeRowIndex -= 1;
}
if (activeRowIndex >= 0) {
grid.alignToIndexFunc(activeRowIndex);
activeRow = grid.getActiveRow();
}
if (!activeRow.getChildWidgetByIndex(activeItemIndex)) {
activeItemIndex = activeRow.getChildWidgetCount() - 1;
}
activeRow.setActiveChildIndex(activeItemIndex);
} else {
self.setActiveChildWidget(self._filters);
self._filters.focus();
}
});
}
});
});