Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions webpack.common.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ module.exports = Merge.smart({
ReactRenderer: './common/static/js/src/ReactRenderer.jsx',
XModuleShim: './xmodule/js/src/xmodule.js',
VerticalStudentView: './xmodule/assets/vertical/public/js/vertical_student_view.js',
VideoBlockMain: './xmodule/assets/video/public/js/video_block_main.js',
commons: 'babel-polyfill'
},

Expand Down
43 changes: 43 additions & 0 deletions xmodule/assets/video/public/js/async_process.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Provides a convenient way to process a large amount of data without UI blocking.
*
* @param {Array} list - The array to process.
* @param {Function} process - The function to execute on each item.
* @returns {Promise<Array>} - Resolves with the processed array.
*/
export const AsyncProcess = {
array(list, process) {
// Validate input
if (!Array.isArray(list)) {
return Promise.reject(new Error('Input is not an array'));
}

if (typeof process !== 'function' || list.length === 0) {
return Promise.resolve(list);
}

const MAX_DELAY = 50;
const result = [];
let index = 0;
const len = list.length;

const handler = (resolve) => {
const start = Date.now();

while (index < len && Date.now() - start < MAX_DELAY) {
result[index] = process(list[index], index);
index++;
}

if (index < len) {
setTimeout(() => handler(resolve), 25);
} else {
resolve(result);
}
};

return new Promise((resolve) => {
setTimeout(() => handler(resolve), 25);
});
}
};
137 changes: 137 additions & 0 deletions xmodule/assets/video/public/js/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import $ from 'jquery';
import _ from 'underscore';

'use strict';

/**
* Video commands module.
*
* @constructor
* @param {Object} state - The object containing the state of the video
* @param {Object} i18n - The object containing strings with translations
* @return {jQuery.Promise} - A resolved jQuery promise
*/
function VideoCommands(state, i18n) {
if (!(this instanceof VideoCommands)) {
return new VideoCommands(state, i18n);
}

_.bindAll(this, 'destroy');
this.state = state;
this.state.videoCommands = this;
this.i18n = i18n;
this.commands = [];
this.initialize();

return $.Deferred().resolve().promise();
}

VideoCommands.prototype = {
/**
* Initializes the module by loading commands and binding events.
*/
initialize: function () {
this.commands = this.getCommands();
this.state.el.on('destroy', this.destroy);
},

/**
* Cleans up the module by removing event handlers and deleting the instance.
*/
destroy: function () {
this.state.el.off('destroy', this.destroy);
delete this.state.videoCommands;
},

/**
* Executes a given command with optional arguments.
*
* @param {String} command - The name of the command to execute
* @param {...*} args - Additional arguments to pass to the command
*/
execute: function (command, ...args) {
if (_.has(this.commands, command)) {
this.commands[command].execute(this.state, ...args);
} else {
console.log(`Command "${command}" is not available.`);
}
},

/**
* Returns the available commands as an object.
*
* @return {Object} - A dictionary of available commands
*/
getCommands: function () {
const commands = {};
const commandsList = [
playCommand,
pauseCommand,
togglePlaybackCommand,
toggleMuteCommand,
toggleFullScreenCommand,
setSpeedCommand,
skipCommand,
];

_.each(commandsList, (command) => {
commands[command.name] = command;
});

return commands;
},
};

/**
* Command constructor.
*
* @constructor
* @param {String} name - The name of the command
* @param {Function} execute - The function to execute the command
*/
function Command(name, execute) {
this.name = name;
this.execute = execute;
}

// Individual command definitions
const playCommand = new Command('play', (state) => {
state.videoPlayer.play();
});

const pauseCommand = new Command('pause', (state) => {
state.videoPlayer.pause();
});

const togglePlaybackCommand = new Command('togglePlayback', (state) => {
if (state.videoPlayer.isPlaying()) {
pauseCommand.execute(state);
} else {
playCommand.execute(state);
}
});

const toggleMuteCommand = new Command('toggleMute', (state) => {
state.videoVolumeControl.toggleMute();
});

const toggleFullScreenCommand = new Command('toggleFullScreen', (state) => {
state.videoFullScreen.toggle();
});

const setSpeedCommand = new Command(
'speed',
(state, speed) => {
state.videoSpeedControl.setSpeed(state.speedToString(speed));
}
);

const skipCommand = new Command('skip', (state, doNotShowAgain) => {
if (doNotShowAgain) {
state.videoBumper.skipAndDoNotShowAgain();
} else {
state.videoBumper.skip();
}
});

export {VideoCommands};
69 changes: 69 additions & 0 deletions xmodule/assets/video/public/js/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict';

/**
* Creates a new object with the specified prototype object and properties.
* @param {Object} o The object which should be the prototype of the newly-created object.
* @private
* @throws {TypeError, Error}
* @return {Object}
*/
const inherit = Object.create || (function () {
const F = function () { };

return function (o) {
if (arguments.length > 1) {
throw Error('Second argument not supported');
}
if (_.isNull(o) || _.isUndefined(o)) {
throw Error('Cannot set a null [[Prototype]]');
}
if (!_.isObject(o)) {
throw TypeError('Argument must be an object');
}

F.prototype = o;
return new F();
};
}());

/**
* Component constructor function.
* Calls `initialize()` if defined.
* @returns {any}
*/
function Component() {
if ($.isFunction(this.initialize)) {
return this.initialize.apply(this, arguments);
}
}

/**
* Adds an `extend` method to the Component constructor.
* Creates a subclass that inherits from Component.
* @param {Object} protoProps - Prototype methods and properties.
* @param {Object} staticProps - Static methods and properties.
* @returns {Function} Child constructor.
*/
Component.extend = function (protoProps, staticProps) {
const Parent = this;

const Child = function () {
if ($.isFunction(this.initialize)) {
return this.initialize.apply(this, arguments);
}
};

Child.prototype = inherit(Parent.prototype);
Child.constructor = Parent;
Child.__super__ = Parent.prototype;

if (protoProps) {
$.extend(Child.prototype, protoProps);
}

$.extend(Child, Parent, staticProps);

return Child;
};

export { Component };
Loading
Loading