Completed
Push — master ( c77b13...c77b13 )
by Jacob
02:57 queued 01:30
created

tinymce/js/premiumcommonmodule.js   A

Complexity

Total Complexity 35
Complexity/F 1.84

Size

Lines of Code 217
Function Count 19

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 35
dl 0
loc 217
rs 9
c 1
b 0
f 0
cc 0
nc 352
mnd 4
bc 36
fnc 19
bpm 1.8947
cpm 1.8421
noi 4

11 Functions

Rating   Name   Duplication   Size   Complexity  
A M.tinymce_recordrtc.create_annotation 0 12 2
A M.tinymce_recordrtc.handle_data_available 0 3 1
A M.tinymce_recordrtc.handle_stop 0 12 1
A premiumcommonmodule.js ➔ d 0 3 1
A M.tinymce_recordrtc.check_secure 0 8 2
C M.tinymce_recordrtc.start_recording 0 70 9
B M.tinymce_recordrtc.init_connection 0 34 1
A M.tinymce_recordrtc.capture_user_media 0 3 1
A M.tinymce_recordrtc.check_browser 0 7 2
A M.tinymce_recordrtc.insert_annotation 0 12 2
B 0 21 5
1
// TinyMCE recordrtc library functions.
2
// @package    tinymce_recordrtc.
3
// @author     Jesus Federico  (jesus [at] blindsidenetworks [dt] com).
4
// @copyright  2016 to present, Blindside Networks Inc.
5
// @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
6
7
// Scrutinizer CI directives.
8
/** global: M */
9
/** global: Y */
10
/** global: recordrtc */
11
/** global: tinyMCEPopup */
12
13
M.tinymce_recordrtc = M.tinymce_recordrtc || {};
14
15
// Extract plugin settings to params hash.
16
(function() {
17
    var params = {};
18
    var r = /([^&=]+)=?([^&]*)/g;
19
20
    var d = function(s) {
21
        return window.decodeURIComponent(s.replace(/\+/g, ' '));
22
    };
23
24
    var search = window.location.search;
25
    var match = r.exec(search.substring(1));
26
    while (match) {
27
        params[d(match[1])] = d(match[2]);
28
29
        if (d(match[2]) === 'true' || d(match[2]) === 'false') {
30
            params[d(match[1])] = d(match[2]) === 'true' ? true : false;
31
        }
32
        match = r.exec(search.substring(1));
33
    }
34
35
    window.params = params;
36
})();
37
38
// Initialize some variables.
39
var alertWarning = null;
40
var alertDanger = null;
41
var mediaRecorder = null;
42
var player = null;
43
var playerDOM = null;
44
var recType = null;
45
var startStopBtn = null;
46
var uploadBtn = null;
47
var socket = null;
48
49
// Notify and redirect user if plugin is used from insecure location.
50
M.tinymce_recordrtc.check_secure = function() {
51
    var isSecureOrigin = (window.location.protocol === 'https:') ||
52
                         (window.location.host.indexOf('localhost') !== -1);
53
54
    if (!isSecureOrigin) {
55
        alertDanger.ancestor().ancestor().removeClass('hide');
56
    }
57
};
58
59
// Display "consider switching browsers" message if not using:
60
// - Firefox 29+;
61
// - Chrome 49+;
62
// - Opera 36+.
63
M.tinymce_recordrtc.check_browser = function() {
64
    if (!((window.bowser.firefox && window.bowser.version >= 29) ||
65
          (window.bowser.chrome && window.bowser.version >= 49) ||
66
          (window.bowser.opera && window.bowser.version >= 36))) {
67
        alertWarning.ancestor().ancestor().removeClass('hide');
68
    }
69
};
70
71
// Attempt to connect to the premium server via Socket.io.
72
M.tinymce_recordrtc.init_connection = function() {
73
    socket.connect();
74
75
    socket.on('connect', function() {
76
        // Send key and secret from Moodle settings
77
        socket.emit('authentication', {
78
            key: window.params.apikey,
79
            secret: window.params.apisecret
80
        });
81
82
        socket.on('authenticated', function() {
83
            // Continue as normal.
84
        });
85
86
        socket.on('unauthorized', function(err) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
87
            Y.use('moodle-core-notification-alert', function() {
88
                new M.core.alert({
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new M.core.alert({Identi...(tinymce_recordrtc)))}) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
89
                    title: M.util.get_string('notpremium_title', 'tinymce_recordrtc'),
90
                    message: M.util.get_string('notpremium', 'tinymce_recordrtc')
91
                });
92
            });
93
        });
94
    });
95
96
    socket.on('connect_error', function() {
97
        socket.disconnect();
98
        Y.use('moodle-core-notification-alert', function() {
99
            new M.core.alert({
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new M.core.alert({Identi...(tinymce_recordrtc)))}) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
100
                title: M.util.get_string('servernotfound_title', 'tinymce_recordrtc'),
101
                message: M.util.get_string('servernotfound', 'tinymce_recordrtc')
102
            });
103
        });
104
    });
105
};
106
107
// Capture webcam/microphone stream.
108
M.tinymce_recordrtc.capture_user_media = function(mediaConstraints, successCallback, errorCallback) {
109
    window.navigator.mediaDevices.getUserMedia(mediaConstraints).then(successCallback).catch(errorCallback);
110
};
111
112
// Push chunks of audio/video to server when made available.
113
M.tinymce_recordrtc.handle_data_available = function(event) {
114
    socket.emit('data available', event.data);
115
};
116
117
// Stop recording and handle end.
118
M.tinymce_recordrtc.handle_stop = function(event) {
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
119
    startStopBtn.set('textContent', 'Start Recording');
120
121
    socket.emit('recording stopped');
122
123
    socket.on('save finished', function(path) {
124
        player.set('src', path);
125
        player.set('controls', true);
126
        player.set('muted', false);
127
        player.ancestor().ancestor().removeClass('hide'); // AUDIO ONLY
128
    });
129
};
130
131
// Get everything set up to start recording.
132
M.tinymce_recordrtc.start_recording = function(type, stream) {
133
    // Generate filename with random ID and file extension.
134
    var fileName = (Math.random() * 1000).toString().replace('.', '');
135
    if (type === 'audio') {
136
        fileName += '-audio.ogg';
137
    } else {
138
        fileName += '-video.webm';
139
    }
140
141
    var data = {
142
        contextid: window.params.contextid,
143
        type: recType,
144
        itemid: window.params.sesskey, // Use session key as item ID.
145
        filename: fileName
146
    };
147
    socket.emit('recording started', data);
148
149
    // The options for the recording codecs and bitrates.
150
    var options = null;
151
    if (type === 'audio') {
152
        if (window.MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
153
            options = {
154
                audioBitsPerSecond: window.params.audiobitrate,
155
                mimeType: 'audio/webm;codecs=opus'
156
            };
157
        } else if (window.MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')) {
158
            options = {
159
                audioBitsPerSecond: window.params.audiobitrate,
160
                mimeType: 'audio/ogg;codecs=opus'
161
            };
162
        }
163
    } else {
164
        if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp9,opus')) {
165
            options = {
166
                audioBitsPerSecond: window.params.audiobitrate,
167
                videoBitsPerSecond: window.params.videobitrate,
168
                mimeType: 'video/webm;codecs=vp9,opus'
169
            };
170
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=h264,opus')) {
171
            options = {
172
                audioBitsPerSecond: window.params.audiobitrate,
173
                videoBitsPerSecond: window.params.videobitrate,
174
                mimeType: 'video/webm;codecs=h264,opus'
175
            };
176
        } else if (window.MediaRecorder.isTypeSupported('video/webm;codecs=vp8,opus')) {
177
            options = {
178
                audioBitsPerSecond: window.params.audiobitrate,
179
                videoBitsPerSecond: window.params.videobitrate,
180
                mimeType: 'video/webm;codecs=vp8,opus'
181
            };
182
        }
183
    }
184
185
    // If none of the options above are supported, fall back on browser defaults.
186
    mediaRecorder = options ? new window.MediaRecorder(stream, options)
187
                            : new window.MediaRecorder(stream);
188
189
    socket.on('recording started', function() {
190
        // Make button clickable again, to allow stopping recording.
191
        startStopBtn.set('textContent', M.util.get_string('stoprecording', 'tinymce_recordrtc'));
192
        startStopBtn.set('disabled', false);
193
194
        // Mute audio, distracting while recording.
195
        player.set('muted', true);
196
197
        mediaRecorder.ondataavailable = M.tinymce_recordrtc.handle_data_available;
198
        mediaRecorder.onstop = M.tinymce_recordrtc.handle_stop;
199
        mediaRecorder.start(1500); // Capture in 1.5s chunks.
200
    });
201
};
202
203
// Generates link to recorded annotation to be inserted.
204
M.tinymce_recordrtc.create_annotation = function(type, recording_url) {
205
    var linkText = window.prompt(M.util.get_string('annotationprompt', 'tinymce_recordrtc'),
206
                                 M.util.get_string('annotation:' + type, 'tinymce_recordrtc'));
207
208
    // Return HTML for annotation link, if user did not press "Cancel".
209
    if (!linkText) {
210
        return undefined;
211
    } else {
212
        var annotation = '<div><a target="_blank" href="' + recording_url + '">' + linkText + '</a></div>';
213
        return annotation;
214
    }
215
};
216
217
// Inserts link to annotation in editor text area.
218
M.tinymce_recordrtc.insert_annotation = function(type, recording_url) {
219
    var annotation = M.tinymce_recordrtc.create_annotation(type, recording_url);
220
221
    // Insert annotation link.
222
    // If user pressed "Cancel", just go back to main recording screen.
223
    if (!annotation) {
224
        uploadBtn.set('textContent', M.util.get_string('attachrecording', 'tinymce_recordrtc'));
225
    } else {
226
        tinyMCEPopup.editor.execCommand('mceInsertContent', false, annotation);
227
        tinyMCEPopup.close();
228
    }
229
};
230