diff --git a/.gitignore b/.gitignore index e3b4732..6ec33fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/dist -/bower_components /node_modules -npm-debug.log +.idea +package-lock.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 87a9eb3..0000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -script: npm run deploy -language: node_js -node_js: -- '0.10' -env: - global: - - GH_REF: github.com/websemantics/vimeo-upload.git - - secure: wIZAh8a5s96MT0CsTs0y06ljBH5UpPl3s10NA1QplHafTtSubWpjE51oUQJ+kzrhB/LMVb051C2Eygmhwa1kXgjeH+shQEJmPSnCRo7p5GLnM5EO4U2M6IXu9Yre7BKL07rHXDeMl5ZlHaR52L+uLCCNAlh/XCNgMu0dlKucGGtOG0mqaoZJdcdTpM7tVtZo5jQvN7Ihe4TbscwaYYNUnaqETiQX3OKTWgmGPkrIq26/6o8St1QkQwZd22R2dwhN2hmEUPrvfWjQxk+hUuNQv8K3vhP8mPhFUuQlxo1S5sv4lvT065ekhanDvm8qju5k6yMQivVftoLMVzhzJUqZY/iyb2BHRyFGwqA3Zz5rqE4HmMRhVXITOdAjPtytAMxk9zdYsKX2NSdTacGN65pKvupeIfQV3GC+HlhpXi2ZtyFwpM42NJYUhA9gUJ92RN7hqIpS2jZdTeWTjOuRcjLxC2JNyGSgIY1tJQ9Tie5MFu5UqBoVPXpoL64I8ZKp8yrnLNW0ccqY/bZEmC+kt0Brhs4TwZLA3+Y1IZVBdeKzs2NS4J8uZbgbacDgavr7sFBkGf3XQIbOXC+hcznKY8R2ugTnAQFYi4JDARvYsyK2zh22bIhq/h5nFsmZIAb2Dft+jnZ2bFBxS1UePV9mEc9PhGEtWc/+5NDjRtBNcEA8VFs= diff --git a/README.md b/README.md index 7c6915b..65547b7 100644 --- a/README.md +++ b/README.md @@ -34,24 +34,148 @@ npm install vimeo-upload Include `vimeo-upload.js` in your index.html. ``` - + ``` -Create a new `VimeoUpload` initialized with a Blob or File and Vimeo Access Token then call `upload()` to start the upload process. +### Basic: +Create a new `VimeoUpload` initialized with a Blob or File and Vimeo Access Token then call `start()` to start the upload process. + +```javascript + +var options = { + token: "TOKEN_STRING_HERE", //Required + file: null, //Required + videoData: { + name: "My awesome title", //Optional + description: "My awesome description" //Optional + } +} + +var uploader = new VimeoUpload(); +uploader.start(options); + +``` + +### Advanced: + +#### All default properties + +List of options that can be overriden. + +``` +| Properties | Description | Default | Required | +|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|----------| +| token | Authentication token created on Vimeo, must have an UPLOAD scope (to be able to upload), and an EDIT scope(to add meta data after upload is complete) | YOUR_TOKEN_HERE | Required | +| file | The File or Blog to upload. | null | Required | +| videoData | Object that supports all video data properties. See link for more info: https://developer.vimeo.com/api/endpoints/videos#PATCH/videos/{video_id} | {} | Optional +| preferredUploadDuration | The preferred chunk upload duration. The chunk size will be updated after each chunk upload to best fit the prefferedUploadDuration. | 20 [seconds] | Optional | +| chunkSize | The size of the chunk to be uploaded | 1024*1024 | Optional | +| supportedFiles | A list of supported file extensions. | ["mov", "mpeg4", "mp4", "avi", "wmv", "mpegps", "flv", "3gpp", "webm"] | Optional | +| upgrade_to_1080 | Upgrade the video to 1080 | false | Optional | +| timeInterval | Time interval for event data to be dispatched. | 150 [miliseconds] | Optional | +| maxAcceptedFails | The number of failures that can occur before the upload is terminated. Fails occur whenever a request fails. Setting this to 0 will allow for unlimited amount of fails. | 20 | Optional | +| maxAcceptedUploadDuration | If the maxAcceptedUploadDuration for a chunk is exceeded, the upload request is aborted and the chunkSize is updated before sending picking up where the upload was left. | 60 [seconds] | Optional | +| useDefaultFileName | Use the file's default name as the video name. | false | Optional | +| retryTimeout | The time before the upload process is resumed when a fail occurs. | 5000 [miliseconds] | Optional | +``` + +##### Usage + + +```javascript + +//All Default options that can be overriden +var options = { + token: "TOKEN_STRING_HERE", //Required + file: null, //Required + videoData: {}, //Check link to see all supported properties | https://developer.vimeo.com/api/endpoints/videos#PATCH/videos/{video_id} + preferredUploadDuration: 20, + chunkSize: 1024*1024, + supportedFiles: ["mov", "mpeg4", "mp4", "avi", "wmv", "mpegps", "flv", "3gpp", "webm"], + upgrade_to_1080: false, + timeInterval: 150, + maxAcceptedFails: 20, + maxAcceptedUploadDuration: 60, + useDefaultFileName: false, + retryTimeout: 5000 +}; + +var uploader = new VimeoUpload(); +uploader.start(options); + +``` + +#### Event Usage + +##### List: + +VimeoUpload comes with different events that can be binded. + +``` +| Event Names | Description | Frequency | [Object object] sent | +|----------------------|---------------------------------------------------------|---------------|-------------------------------------------------------------------------------------------| +| chunkprogresschanged | Regularly sends the current percent of a chunk upload | Default 150ms | { detail: number } | +| totalprogresschanged | Regularly sends the current percent of the total upload | Default 150ms | { detail: number } | +| vimeouploaderror | Emits if any errors occurs | N/A | { detail: { message: string, error: [Object object] } } | +| vimeouploadcomplete | Called once when the upload is completed | Once | { detail: { id: number, link: string, name: string, uri: string, createdTime: string } } | +``` + + +##### Usage: ```javascript -var uploader = new VimeoUpload({ - file: file, - token: accessToken, -}); -uploader.upload(); + //Get the progress bar elements + var totalProgress = document.getElementById("progress-total"); + var chunkProgress = document.getElementById("progress-chunk"); + + //Create the VimeoUpload object + var vimeoUpload = new VimeoUpload(); + + vimeoUpload.on("chunkprogresschanged", function(event){ + var progress = event.detail; + chunkProgress.setAttribute('style', 'width:' + progress + '%'); + chunkProgress.innerHTML = ' ' + progress + '%' + + }); + + vimeoUpload.on("totalprogresschanged", function(event){ + var progress = event.detail; + totalProgress.setAttribute('style', 'width:' + progress + '%'); + totalProgress.innerHTML = ' ' + progress + '%' + }); + + vimeoUpload.on("vimeouploaderror", function(event){ + console.log(event.detail.message, event.detail.error); + }); +id: vimeoId, + link: data.link, + name: data.name, + uri: data.uri, + createdTime: data.created_time + vimeoUpload.on("vimeouploadcomplete", function(event){ + + console.log("Meta data", event.detail); + + //Properties returned + //var vimeoId = event.detail.id; + //var link = event.detail.link; + //var name = event.detail.name; + //var uri = event.detail.uri; + //var createdTime = event.detail.created_time; + + + }); + + //Start upload + vimeoUpload.start(options); + ``` -Your access token need to be authorized by Vimeo. Create new Vimeo access token [here](https://developer.vimeo.com/apps). +Your access token need to be authorized by Vimeo. Ensure it has an "EDIT" and "UPLOAD" scope. Create new Vimeo access token [here](https://developer.vimeo.com/apps). Check `index.html` for details and additional parameters you can include when initializing `VimeoUpload`. ## Credits -Sample code for uploading files directly with XHR/CORS: [cors-upload-sample](https://github.com/googledrive/cors-upload-sample) +Sample code for uploading files directly with XHR/CORS: [cors-upload-sample](https://github.com/googledrive/cors-upload-sample) \ No newline at end of file diff --git a/bower.json b/bower.json deleted file mode 100644 index 92bd079..0000000 --- a/bower.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "vimeo-upload", - "main": "vimeo-upload.js", - "version": "0.1.6", - "homepage": "https://github.com/websemantics/vimeo-upload", - "authors": [ - "Adnan Sh. Sagar, PhD. " - ], - "description": "Upload videos to your Vimeo account and update their metadata directly from a browser or a Node.js app.", - "keywords": [ - "vimeo", - "video", - "upload", - "node", - "browser" - ], - "license": "Apache 2.0", - "ignore": [ - "**/.*", - "node_modules", - "test", - "tests" - ] -} diff --git a/dist/vimeo-upload.js b/dist/vimeo-upload.js new file mode 100644 index 0000000..02738bc --- /dev/null +++ b/dist/vimeo-upload.js @@ -0,0 +1,1228 @@ +var VimeoUpload = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 6); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var request_1 = __webpack_require__(9); +var header_1 = __webpack_require__(10); +var response_1 = __webpack_require__(11); +var utils_1 = __webpack_require__(2); +var status_enum_1 = __webpack_require__(1); +/** + * Created by kfaulhaber on 31/03/2017. + */ +var HttpService = (function () { + /** + * constructor + * @param maxAcceptedUploadDuration + */ + function HttpService(maxAcceptedUploadDuration) { + this.maxAcceptedUploadDuration = maxAcceptedUploadDuration; + } + /** + * DefaultResolver that decides if the xhr response is valid, and sends custom Response + * @param xhr + * @returns {Response} + * @constructor + */ + HttpService.DefaultResolver = function (xhr) { + var data = null; + try { + data = JSON.parse(xhr.response); + } + catch (e) { + data = xhr.response; + } + var response = new response_1.Response(xhr.status, xhr.statusText, data); + response.responseHeaders = xhr.getAllResponseHeaders().split("\r\n").filter(function (rawHeader) { + return rawHeader.length > 0; + }).map(function (rawHeader) { + var index = rawHeader.indexOf(":"); + return new header_1.Header(rawHeader.slice(0, index).trim(), rawHeader.slice(index + 1).trim()); + }); + if (xhr.status > 308) { + response.statusCode = status_enum_1.Status.Rejected; + } + else { + response.statusCode = status_enum_1.Status.Resolved; + } + return response; + }; + /** + * send method that sets the headers, the different callbacks and sends a request with data. + * @param request + * @param statData + * @returns {Promise} + */ + HttpService.prototype.send = function (request, statData) { + if (statData === void 0) { statData = null; } + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open(request.method, request.url, true); + request.headers.forEach(function (header) { return xhr.setRequestHeader(header.title, header.value); }); + xhr.onload = function () { + if (statData !== null) { + statData.end = new Date(); + statData.done = true; + } + var response = HttpService.DefaultResolver(xhr); + switch (true) { + case response.statusCode === status_enum_1.Status.Resolved: + resolve(response); + break; + default: + reject(response); + } + }; + xhr.onabort = function () { + reject(new response_1.Response(xhr.status, xhr.statusText, xhr.response)); + }; + xhr.onerror = function () { + reject(new response_1.Response(xhr.status, xhr.statusText, xhr.response)); + }; + if (statData != null) { + xhr.upload.addEventListener("progress", function (data) { + if (data.lengthComputable) { + statData.loaded = data.loaded; + statData.total = data.total; + statData.end = new Date(); + //TODO: Symplify this. + if (utils_1.TimeUtil.TimeToSeconds(statData.end.getTime() - statData.start.getTime()) > statData.prefferedDuration * 2) { + statData.loaded = 0; + statData.total = 0; + statData.done = true; + xhr.abort(); + } + } + }); + } + try { + xhr.send(request.data); + } + catch (e) { + console.error("An error occured while sending.", e); + } + }); + }; + /** + * Method that takes raw information to build a Request object. + * @param method + * @param url + * @param data + * @param headers + * @returns {Request} + * @constructor + */ + HttpService.CreateRequest = function (method, url, data, headers) { + if (data === void 0) { data = null; } + if (headers === void 0) { headers = null; } + var headerList = []; + for (var prop in headers) { + if (headers.hasOwnProperty(prop)) { + headerList.push(new header_1.Header(prop, headers[prop])); + } + } + return new request_1.Request(method, url, data, headerList); + }; + return HttpService; +}()); +exports.HttpService = HttpService; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 26/07/2017. + * + * Status enum for setting the status of a custom Response + * + */ +exports.__esModule = true; +var Status; +(function (Status) { + Status[Status["Neutral"] = 0] = "Neutral"; + Status[Status["Rejected"] = 1] = "Rejected"; + Status[Status["Resolved"] = 2] = "Resolved"; +})(Status = exports.Status || (exports.Status = {})); + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 17/07/2017. + */ +exports.__esModule = true; +var TimeUtil = (function () { + function TimeUtil() { + } + /** + * TimeToSeconds method that converts miliseconds to seconds + * @param time + * @returns {number} + * @constructor + */ + TimeUtil.TimeToSeconds = function (time) { + return time / 1000; + }; + /** + * TimeToString method that takes a time and converts it to a string. + * @param time + * @returns {string} + * @constructor + */ + TimeUtil.TimeToString = function (time) { + var date = new Date(null); + date.setTime(time); + return date.toISOString().substr(11, 8); + }; + /** + * MilisecondsToString method that converts miliseconds to a string time format. HH:MM:SS + * @param miliseconds + * @returns {string} + * @constructor + */ + TimeUtil.MilisecondsToString = function (miliseconds) { + var seconds = TimeUtil.TimeToSeconds(miliseconds); + var date = new Date(null); + date.setSeconds(seconds); + return date.toISOString().substr(11, 8); + }; + return TimeUtil; +}()); +exports.TimeUtil = TimeUtil; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by Kfaulhaber on 30/06/2017. + * + * Basic route creater + * + */ +exports.__esModule = true; +exports.VIMEO_ROUTES = { + DEFAULT: function (uri) { + if (uri === void 0) { uri = ""; } + return "https://api.vimeo.com" + uri; + }, + TICKET: function () { return exports.VIMEO_ROUTES.DEFAULT() + "/me/videos"; }, + VIDEOS: function (videoId) { return "" + exports.VIMEO_ROUTES.DEFAULT("/videos/" + videoId); } +}; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 13/07/2017. + */ +exports.__esModule = true; +exports.DEFAULT_VALUES = { + preferredUploadDuration: 20, + chunkSize: 1024 * 1024, + token: "TOKEN_STRING_HERE", + supportedFiles: ["mov", "mpeg4", "mp4", "avi", "wmv", "mpegps", "flv", "3gpp", "webm"], + name: "", + description: "", + file: null, + upgrade_to_1080: false, + timeInterval: 150, + maxAcceptedFails: 20, + maxAcceptedUploadDuration: 60, + useDefaultFileName: false, + retryTimeout: 5000, + videoData: {} //See link for a full list of supported metaData | https://developer.vimeo.com/api/endpoints/videos#PATCH/videos/{video_id} +}; +exports.DEFAULT_EVENTS = { + chunkprogresschanged: function (event) { return console.log("Default: Chunk Progress Update: " + event.detail + "/100"); }, + totalprogresschanged: function (event) { return console.log("Default: Total Progress Update: " + event.detail + "/100"); }, + vimeouploaderror: function () { }, + vimeouploadcomplete: function () { } +}; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var config_1 = __webpack_require__(4); +/** + * Created by kfaulhaber on 17/07/2017. + * + * EventService class + * + * Composed of static methods for handly events + * + */ +var EventService = (function () { + function EventService() { + } + /** + * Add static method that registers a valid event name. + * @param eventName + * @param callback + * @constructor + */ + EventService.Add = function (eventName, callback) { + window.addEventListener(eventName, callback, false); + }; + /** + * Remove static method that unregisters a listener with a valid event name + * @param eventName + * @param callback + * @constructor + */ + EventService.Remove = function (eventName, callback) { + window.removeEventListener(eventName, callback, false); + }; + /** + * Dispatch static method that emits an event + * @param eventName + * @param data + * @constructor + */ + EventService.Dispatch = function (eventName, data) { + if (data === void 0) { data = null; } + var customEvent = new CustomEvent(eventName, { detail: data }); + window.dispatchEvent(customEvent); + }; + /** + * Exists static method that checks if an event name is valid. + * @param eventName + * @returns {boolean} + * @constructor + */ + EventService.Exists = function (eventName) { + return config_1.DEFAULT_EVENTS.hasOwnProperty(eventName); + }; + /** + * GetDefault static method that returns the default handler for a given event. + * @param eventName + * @returns {any} + * @constructor + */ + EventService.GetDefault = function (eventName) { + return config_1.DEFAULT_EVENTS[eventName]; + }; + return EventService; +}()); +exports.EventService = EventService; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var app_1 = __webpack_require__(7); +var module; +/** + * Created by kfaulhaber on 30/06/2017. + */ +/** + * Binding library to exports + * @type {App} + */ +module.exports = app_1.App; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var ticket_service_1 = __webpack_require__(8); +var chunk_service_1 = __webpack_require__(13); +var upload_service_1 = __webpack_require__(15); +var config_1 = __webpack_require__(4); +var event_service_1 = __webpack_require__(5); +var validator_service_1 = __webpack_require__(16); +var media_service_1 = __webpack_require__(17); +var http_service_1 = __webpack_require__(0); +var stat_service_1 = __webpack_require__(19); +var App = (function () { + function App() { + //Defining other properties + this.failCount = 0; + } + /** + * Method that initializes the VimeoUpload library. Called everytime an upload is started. + * Resets all the services and properties. To see "config/config.ts" for all properties that can be added to options. + * @param options + */ + App.prototype.init = function (options) { + if (options === void 0) { options = {}; } + var values = {}; + //We loop through all the default values and see if options overides specific ones. All new properties are added to values object. + for (var prop in config_1.DEFAULT_VALUES) { + if (config_1.DEFAULT_VALUES.hasOwnProperty(prop)) { + values[prop] = (options.hasOwnProperty(prop)) ? options[prop] : config_1.DEFAULT_VALUES[prop]; + } + } + this.maxAcceptedFails = values.maxAcceptedFails; + this.httpService = new http_service_1.HttpService(values.maxAcceptedUploadDuration); + this.mediaService = new media_service_1.MediaService(this.httpService, values.file, values.videoData, values.upgrade_to_1080, values.useDefaultFileName); + this.chunkService = new chunk_service_1.ChunkService(this.mediaService, values.preferredUploadDuration, values.chunkSize); + this.statService = new stat_service_1.StatService(values.timeInterval, this.chunkService); + this.ticketService = new ticket_service_1.TicketService(values.token, this.httpService, values.upgrade_to_1080); + this.uploadService = new upload_service_1.UploadService(this.mediaService, this.ticketService, this.httpService, this.statService); + this.validatorService = new validator_service_1.ValidatorService(values.supportedFiles); + }; + /** + * Start method that'll initiate the upload, create the upload ticket and start the upload loop. + * @param options + */ + App.prototype.start = function (options) { + var _this = this; + if (options === void 0) { options = {}; } + this.init(options); + //TODO: Add error if not supported. + if (!this.validatorService.isSupported(this.mediaService.media.file)) + return; + this.ticketService.open() + .then(function (response) { + console.log(response); + _this.ticketService.save(response); + _this.statService.start(); + _this.process(); + })["catch"](function (error) { + if (_this.canContinue()) { + _this.failCount++; + event_service_1.EventService.Dispatch("vimeouploaderror", { message: "Error creating ticket.", error: error }); + setTimeout(function () { + _this.start(options); + }, _this.retryTimeout); + } + }); + }; + /** + * Process method that will seek the next chunk to upload + */ + App.prototype.process = function () { + var _this = this; + var chunk = this.chunkService.create(); + this.uploadService.send(chunk).then(function (response) { + _this.chunkService.updateSize(_this.statService.getChunkUploadDuration()); + _this.check(); + })["catch"](function (error) { + if (_this.canContinue()) { + _this.failCount++; + event_service_1.EventService.Dispatch("vimeouploaderror", { message: "Error sending chunk.", error: error }); + _this.chunkService.updateSize(_this.statService.getChunkUploadDuration()); + setTimeout(function () { + _this.check(); + }, _this.retryTimeout); + } + }); + }; + /** + * Check method that is called after each chunk upload to update the byte range. + */ + App.prototype.check = function () { + var _this = this; + this.uploadService.getRange().then(function (response) { + switch (response.status) { + case 308: + //noinspection TypeScriptValidateTypes + var range = response.responseHeaders.find(function (header) { + if (header === null && header === undefined) + return false; + return header.title === "Range"; + }); + _this.chunkService.updateOffset(range.value); + if (_this.chunkService.isDone()) { + _this.done(); + return; + } + _this.process(); + break; + case 200 || 201: + _this.done(); + break; + default: + console.warn("Unrecognized status code (" + response.status + ") for chunk range."); + } + })["catch"](function (error) { + event_service_1.EventService.Dispatch("vimeouploaderror", { message: "Unable to get range.", error: error }); + if (_this.canContinue()) { + _this.failCount++; + setTimeout(function () { + _this.check(); + }, _this.retryTimeout); + } + }); + }; + /** + * Done method that is called when an upload has been completed. Closes the upload ticket. + */ + App.prototype.done = function () { + var _this = this; + this.statService.totalStatData.done = true; + this.ticketService.close().then(function (response) { + _this.statService.stop(); + try { + //noinspection TypeScriptValidateTypes + var vimeoId = parseInt(response.responseHeaders.find(function (header) { + //noinspection TypeScriptValidateTypes + if (header === null && header === undefined) + return false; + return header.title === "Location"; + }).value.replace("/videos/", "")); + _this.updateVideo(vimeoId); + } + catch (error) { + console.log("Error retrieving Vimeo Id."); + } + console.log("Delete success:", response); + })["catch"](function (error) { + _this.statService.stop(); + event_service_1.EventService.Dispatch("vimeouploaderror", { message: "Unable to close upload ticket.", error: error }); + }); + }; + /** + * UpdateVideo method + * @param vimeoId + */ + App.prototype.updateVideo = function (vimeoId) { + this.mediaService.updateVideoData(this.ticketService.token, vimeoId).then(function (response) { + var meta = media_service_1.MediaService.GetMeta(vimeoId, response.data); + event_service_1.EventService.Dispatch("vimeouploadcomplete", meta); + })["catch"](function (error) { + event_service_1.EventService.Dispatch("vimeouploaderror", { message: "Unable to update video " + vimeoId + " with name and description.", error: error }); + }); + }; + /** + * on method to add a listener. See config/config.ts for a list of available events + * @param eventName + * @param callback + */ + App.prototype.on = function (eventName, callback) { + if (callback === void 0) { callback = null; } + if (!event_service_1.EventService.Exists(eventName)) + return; + if (callback === null) { + callback = event_service_1.EventService.GetDefault(eventName); + } + event_service_1.EventService.Add(eventName, callback); + }; + /** + * off method to remove a listener. See config/config.ts for a list of available events + * @param eventName + * @param callback + */ + App.prototype.off = function (eventName, callback) { + if (callback === void 0) { callback = null; } + if (!event_service_1.EventService.Exists(eventName)) + return; + if (callback === null) { + callback = event_service_1.EventService.GetDefault(eventName); + } + event_service_1.EventService.Remove(eventName, callback); + }; + /** + * canContinue method checks to see if the amount of failCounts exceed the maxAcceptedFails + * @returns {boolean} + */ + App.prototype.canContinue = function () { + return (this.maxAcceptedFails === 0) ? true : (this.failCount <= this.maxAcceptedFails) ? true : false; + }; + return App; +}()); +exports.App = App; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var http_service_1 = __webpack_require__(0); +var ticket_1 = __webpack_require__(12); +var routes_1 = __webpack_require__(3); +/** + * Created by kfaulhaber on 30/06/2017. + */ +var TicketService = (function () { + /** + * constructor that takes 3 paramaters + * @param token + * @param httpService + * @param upgrade_to_1080 + */ + function TicketService(token, httpService, upgrade_to_1080) { + this.token = token; + this.httpService = httpService; + this.upgrade_to_1080 = upgrade_to_1080; + } + /** + * open method that creates a ticket request + * @returns {Promise} + */ + TicketService.prototype.open = function () { + var data = { type: 'streaming' }; + if (this.upgrade_to_1080) { + data["upgrade_to_1080"] = this.upgrade_to_1080; + } + var request = http_service_1.HttpService.CreateRequest("POST", routes_1.VIMEO_ROUTES.TICKET(), JSON.stringify(data), { + Authorization: "Bearer " + this.token, + 'Content-Type': 'application/json' + }); + return this.httpService.send(request); + }; + /** + * save method that takes a response from creating a ticket upload request and saves it + * @param response + */ + TicketService.prototype.save = function (response) { + this.ticket = new ticket_1.Ticket(response.data.upload_link_secure, response.data.ticket_id, response.data.upload_link, response.data.complete_uri, response.data.user); + }; + /** + * close method that sends a DELETE request to the ticket's complete Uri to complete and finalize the upload. + * Called at the end of the upload when all the bytes have been sent. + * @returns {Promise} + */ + TicketService.prototype.close = function () { + var request = http_service_1.HttpService.CreateRequest("DELETE", routes_1.VIMEO_ROUTES.DEFAULT(this.ticket.completeUri), null, { + Authorization: "Bearer " + this.token + }); + return this.httpService.send(request); + }; + return TicketService; +}()); +exports.TicketService = TicketService; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +/** + * Created by kfaulhaber on 17/07/2017. + * + * Custom Request Entity + * + */ +var Request = (function () { + function Request(method, url, data, headers) { + if (data === void 0) { data = null; } + if (headers === void 0) { headers = []; } + this.method = method; + this.url = url; + this.data = data; + this.headers = headers; + } + return Request; +}()); +exports.Request = Request; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 24/07/2017. + * + * Header Class Entity + */ +exports.__esModule = true; +var Header = (function () { + function Header(title, value) { + this.title = title; + this.value = value; + } + return Header; +}()); +exports.Header = Header; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var status_enum_1 = __webpack_require__(1); +/** + * Created by kfaulhaber on 20/07/2017. + * + * Custom Response Entity + * + */ +var Response = (function () { + function Response(status, statusText, data) { + if (data === void 0) { data = null; } + this.status = status; + this.statusText = statusText; + this.data = data; + this.statusCode = status_enum_1.Status.Neutral; + } + return Response; +}()); +exports.Response = Response; + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 13/07/2017. + * + * Ticket Entity + * + */ +exports.__esModule = true; +var Ticket = (function () { + function Ticket(uploadLinkSecure, ticketId, uploadLink, completeUri, user) { + this.uploadLinkSecure = uploadLinkSecure; + this.ticketId = ticketId; + this.uploadLink = uploadLink; + this.completeUri = completeUri; + this.user = user; + } + return Ticket; +}()); +exports.Ticket = Ticket; + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var chunk_1 = __webpack_require__(14); +/** + * Created by kfaulhaber on 30/06/2017. + */ +var ChunkService = (function () { + /** + * constructor + * @param mediaService + * @param preferredUploadDuration + * @param size + * @param offset + */ + function ChunkService(mediaService, preferredUploadDuration, size, offset) { + if (offset === void 0) { offset = 0; } + this.mediaService = mediaService; + this.preferredUploadDuration = preferredUploadDuration; + this.size = size; + this.offset = offset; + } + /** + * updateSize method that updates the next chunk size based on the uploadDuration compares to the prefferedUploadDuration + * @param uploadDuration + */ + ChunkService.prototype.updateSize = function (uploadDuration) { + this.size = Math.floor((this.size * this.preferredUploadDuration) / uploadDuration * ChunkService.Adjuster); + }; + /** + * create method that returns the next chunk to upload from the byte array + * @returns {Chunk} + */ + ChunkService.prototype.create = function () { + var end = Math.min(this.offset + this.size, this.mediaService.media.file.size); + //TODO: Simplify + if (end - this.offset !== this.size) { + this.updateSize(end - this.offset); + } + var content = this.mediaService.media.file.slice(this.offset, end); + return new chunk_1.Chunk(content, "bytes " + this.offset + "-" + end + "/" + this.mediaService.media.file.size); + }; + /** + * updateOffset method that takes a range and updates the offset. + * @param range + */ + ChunkService.prototype.updateOffset = function (range) { + this.offset = parseInt(range.match(/\d+/g).pop(), 10) + 1; + }; + /** + * isDone method that checks to see if the offset is or is superior to the file size. + * @returns {boolean} + */ + ChunkService.prototype.isDone = function () { + return this.offset >= this.mediaService.media.file.size; + }; + ChunkService.Adjuster = 0.7; + return ChunkService; +}()); +exports.ChunkService = ChunkService; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 13/07/2017. + * + * Chunk Entity + * + */ +exports.__esModule = true; +var Chunk = (function () { + function Chunk(content, contentRange) { + this.content = content; + this.contentRange = contentRange; + } + return Chunk; +}()); +exports.Chunk = Chunk; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var http_service_1 = __webpack_require__(0); +/** + * Created by kfaulhaber on 30/06/2017. + */ +var UploadService = (function () { + /** + * constructor that has mulitple dependencies to other services + * @param mediaService + * @param ticketService + * @param httpService + * @param statService + */ + function UploadService(mediaService, ticketService, httpService, statService) { + this.mediaService = mediaService; + this.ticketService = ticketService; + this.httpService = httpService; + this.statService = statService; + } + /** + * Method that sends a request with the video chunk data + * @param chunk + * @returns {Promise} + */ + UploadService.prototype.send = function (chunk) { + var statData = this.statService.create(); + this.statService.save(statData); + var request = http_service_1.HttpService.CreateRequest("PUT", this.ticketService.ticket.uploadLinkSecure, chunk.content, { + 'Content-Type': this.mediaService.media.file.type, + 'Content-Range': chunk.contentRange + }); + return this.httpService.send(request, statData); + }; + /** + * getRange method that gets the byte range of the already uploaded video content + * @returns {Promise} + */ + UploadService.prototype.getRange = function () { + var request = http_service_1.HttpService.CreateRequest("PUT", this.ticketService.ticket.uploadLinkSecure, null, { + 'Content-Type': this.mediaService.media.file.type, + 'Content-Range': 'bytes */* ' + }); + return this.httpService.send(request); + }; + return UploadService; +}()); +exports.UploadService = UploadService; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 30/06/2017. + */ +exports.__esModule = true; +var ValidatorService = (function () { + /** + * constructor that takes in a list of supported video files + * @param supportedFiles + */ + function ValidatorService(supportedFiles) { + this.supportedFiles = supportedFiles; + } + /** + * Method that takes a file and decides whether it's supported + * @param file + * @returns {boolean} + */ + ValidatorService.prototype.isSupported = function (file) { + var type = file.type; + if (type.indexOf('/') === -1) { + console.warn("Wrong type found (" + type + ")."); + return false; + } + var split = type.split('/'); + if (split[0] !== "video") { + console.warn("Only videos are supported, " + type + " given."); + return false; + } + return this.supportedFiles.includes(split[1]); + }; + return ValidatorService; +}()); +exports.ValidatorService = ValidatorService; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var media_1 = __webpack_require__(18); +var http_service_1 = __webpack_require__(0); +var routes_1 = __webpack_require__(3); +/** + * Created by kfaulhaber on 21/07/2017. + */ +var MediaService = (function () { + /** + * constructor that initiates the services with the list of dependencies + * @param httpService + * @param file + * @param data + * @param upgrade_to_1080 + * @param useDefaultFileName + */ + function MediaService(httpService, file, data, upgrade_to_1080, useDefaultFileName) { + this.httpService = httpService; + if (useDefaultFileName) { + data["name"] = file.name; + } + this.media = new media_1.Media(file, data, upgrade_to_1080); + } + /** + * updateVideoData method that sends a request to edit video information. + * Will not work if the token does not have the "EDIT" scope. Will return a 403 forbidden. + * @param {string} token + * @param {number} vimeoId + * @returns {Promise} + */ + MediaService.prototype.updateVideoData = function (token, vimeoId) { + var params = this.media.data; + var query = Object.keys(params).map(function (key) { return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]); }).join('&'); + console.log(query); + var request = http_service_1.HttpService.CreateRequest("PATCH", routes_1.VIMEO_ROUTES.VIDEOS(vimeoId), query, { + Authorization: "Bearer " + token + }); + return this.httpService.send(request); + }; + /** + * GetMeta static method returns an object with data from updateVideoData response + * @param {number} vimeoId + * @param {object} data + * @returns {{id: number, link: (any|HTMLLinkElement|(function(string): string)), name: any, uri: any, createdTime: any}} + */ + MediaService.GetMeta = function (vimeoId, data) { + return { + id: vimeoId, + link: data.link, + name: data.name, + uri: data.uri, + createdTime: data.created_time + }; + }; + return MediaService; +}()); +exports.MediaService = MediaService; + + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 20/07/2017. + */ +exports.__esModule = true; +var Media = (function () { + /** + * constructor + * @param file + * @param data + * @param upgrade_to_1080 + */ + function Media(file, data, upgrade_to_1080) { + this.file = file; + this.data = data; + this.upgrade_to_1080 = upgrade_to_1080; + } + return Media; +}()); +exports.Media = Media; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +exports.__esModule = true; +var event_service_1 = __webpack_require__(5); +var utils_1 = __webpack_require__(2); +var stat_data_1 = __webpack_require__(20); +/** + * Created by Grimbode on 14/07/2017. + * + * Service that takes care of checking the total uploaded content and dispatches events to notify all listeners. + * + */ +var StatService = (function () { + /** + * constructor that takes two dependencies timerInterval and chunkService + * @param timeInterval + * @param chunkService + */ + function StatService(timeInterval, chunkService) { + this.timeInterval = timeInterval; + this.chunkService = chunkService; + this.si = -1; + this.previousTotalPercent = 0; + } + /** + * start method that starts the interval loop to constantly dispatch events with updated information. + */ + StatService.prototype.start = function () { + this.totalStatData = this.create(true); + this.startInterval(); + }; + /** + * create method creates a new statData with information from chunkservice. + * @param isTotal + * @returns {StatData} + */ + StatService.prototype.create = function (isTotal) { + if (isTotal === void 0) { isTotal = false; } + var date = new Date(); + var size = (isTotal) ? this.chunkService.mediaService.media.file.size : this.chunkService.size; + var statData = new stat_data_1.StatData(date, date, this.chunkService.preferredUploadDuration, 0, size); + return statData; + }; + /** + * save method that takes a statData and saves it to the chunkStatData + * @param timeData + */ + StatService.prototype.save = function (timeData) { + this.chunkStatData = timeData; + }; + /** + * calculateRatio method that calculates the decimal percent of how much has been uploaded (can be chunk or total) + * @param loaded + * @param total + * @returns {number} + */ + StatService.prototype.calculateRatio = function (loaded, total) { + return loaded / total; + }; + /** + * calculatePercent method calculates the percent that has been uploaded. + * @param loaded + * @param total + * @returns {number} + */ + StatService.prototype.calculatePercent = function (loaded, total) { + return Math.floor(this.calculateRatio(loaded, total) * 100); + }; + /** + * updateTotal method that updates the total percent that has currently been uploaded. + */ + StatService.prototype.updateTotal = function () { + this.totalStatData.loaded += this.chunkStatData.total; + }; + /** + * startInterval method that starts the interval loop to continously dispatch events with updated information on what has been uploaded. + */ + StatService.prototype.startInterval = function () { + var _this = this; + if (this.si > -1) { + this.stop(); + } + this.si = setInterval(function () { + var chunkPercent = _this.calculatePercent(_this.chunkStatData.loaded, _this.chunkStatData.total); + if (_this.chunkStatData.done) { + _this.updateTotal(); + _this.chunkStatData.total = _this.chunkStatData.loaded = 0; + chunkPercent = 100; + } + _this.totalStatData.loaded = Math.max(_this.chunkService.offset, _this.totalStatData.loaded); + _this.totalStatData.end = _this.chunkStatData.end; + _this.previousTotalPercent = Math.max(_this.totalStatData.loaded + _this.chunkStatData.loaded, _this.previousTotalPercent); + var totalPercent = _this.calculatePercent(_this.previousTotalPercent, _this.totalStatData.total); + event_service_1.EventService.Dispatch("chunkprogresschanged", chunkPercent); + if (_this.totalStatData.done) { + totalPercent = 100; + } + event_service_1.EventService.Dispatch("totalprogresschanged", totalPercent); + }, this.timeInterval); + }; + /** + * stop method that stops the interval loop, which will stop the flow of dispatched events. + */ + StatService.prototype.stop = function () { + clearInterval(this.si); + }; + /** + * getChunkUploadDuration method that returns the current time it has taken to upload a chunk. + * @returns {number} + */ + StatService.prototype.getChunkUploadDuration = function () { + return utils_1.TimeUtil.TimeToSeconds(this.chunkStatData.end.getTime() - this.chunkStatData.start.getTime()); + }; + /** + * chunkIsOverPrefferedUploadTime method that checks if the duration time has exceeded the preffered upload duration. + * @returns {boolean} + */ + StatService.prototype.chunkIsOverPrefferedUploadTime = function () { + return this.getChunkUploadDuration() >= this.chunkService.preferredUploadDuration * 1.5; + }; + return StatService; +}()); +exports.StatService = StatService; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Created by kfaulhaber on 24/07/2017. + * + * StatData Entity + * + */ +exports.__esModule = true; +var StatData = (function () { + function StatData(start, end, prefferedDuration, loaded, total, done) { + if (loaded === void 0) { loaded = 0; } + if (total === void 0) { total = 0; } + if (done === void 0) { done = false; } + this.start = start; + this.end = end; + this.prefferedDuration = prefferedDuration; + this.loaded = loaded; + this.total = total; + this.done = done; + } + return StatData; +}()); +exports.StatData = StatData; + + +/***/ }) +/******/ ]); +//# sourceMappingURL=vimeo-upload.js.map \ No newline at end of file diff --git a/dist/vimeo-upload.js.map b/dist/vimeo-upload.js.map new file mode 100644 index 0000000..1b3ff60 --- /dev/null +++ b/dist/vimeo-upload.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap d583644d924b1c03bf19","webpack:///./src/services/http/http.service.ts","webpack:///./src/enums/status.enum.ts","webpack:///./src/utils/utils.ts","webpack:///./src/routes/routes.ts","webpack:///./src/config/config.ts","webpack:///./src/services/event/event.service.ts","webpack:///./src/main.ts","webpack:///./src/app.ts","webpack:///./src/services/ticket/ticket.service.ts","webpack:///./src/entities/request.ts","webpack:///./src/entities/header.ts","webpack:///./src/entities/response.ts","webpack:///./src/entities/ticket.ts","webpack:///./src/services/chunk/chunk.service.ts","webpack:///./src/entities/chunk.ts","webpack:///./src/services/upload/upload.service.ts","webpack:///./src/services/validator/validator.service.ts","webpack:///./src/services/media/media.service.ts","webpack:///./src/entities/media.ts","webpack:///./src/services/stat/stat.service.ts","webpack:///./src/entities/stat_data.ts"],"names":[],"mappings":"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","file":"vimeo-upload.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap d583644d924b1c03bf19","import {Request} from \"../../entities/request\";\nimport {Header} from \"../../entities/header\";\nimport {Response} from \"../../entities/response\";\nimport {StatData} from \"../../entities/stat_data\";\nimport {TimeUtil} from \"../../utils/utils\";\nimport {Status} from \"../../enums/status.enum\";\n/**\n * Created by kfaulhaber on 31/03/2017.\n */\n \n \nexport class HttpService {\n\n /**\n * constructor\n * @param maxAcceptedUploadDuration\n */\n constructor(\n public maxAcceptedUploadDuration: number\n ){}\n\n\n /**\n * DefaultResolver that decides if the xhr response is valid, and sends custom Response\n * @param xhr\n * @returns {Response}\n * @constructor\n */\n public static DefaultResolver(xhr: XMLHttpRequest): Response {\n let data = null;\n\n try{\n data = JSON.parse(xhr.response);\n }catch(e){\n data = xhr.response;\n }\n\n let response = new Response(\n xhr.status,\n xhr.statusText,\n data\n );\n\n response.responseHeaders = xhr.getAllResponseHeaders().split(\"\\r\\n\").filter((rawHeader: string) => {\n return rawHeader.length > 0;\n }).map((rawHeader: string)=>{\n let index = rawHeader.indexOf(\":\");\n return new Header(rawHeader.slice(0, index).trim(), rawHeader.slice(index+1).trim());\n });\n\n if(xhr.status > 308){\n response.statusCode = Status.Rejected\n }else{\n response.statusCode = Status.Resolved\n }\n \n return response;\n }\n\n /**\n * send method that sets the headers, the different callbacks and sends a request with data.\n * @param request\n * @param statData\n * @returns {Promise}\n */\n public send(request: Request, statData: StatData = null): Promise{\n return new Promise((resolve: any, reject: any) => {\n let xhr = new XMLHttpRequest();\n\n xhr.open(request.method, request.url, true);\n request.headers.forEach((header: Header)=> xhr.setRequestHeader(header.title, header.value));\n\n xhr.onload = () => {\n if(statData !== null){\n statData.end = new Date();\n statData.done = true;\n }\n\n let response = HttpService.DefaultResolver(xhr);\n\n\n switch(true){\n case response.statusCode === Status.Resolved:\n resolve(response);\n break;\n default:\n reject(response);\n }\n };\n\n xhr.onabort = () => {\n reject(new Response(xhr.status, xhr.statusText, xhr.response));\n };\n\n xhr.onerror = () => {\n reject(new Response(xhr.status, xhr.statusText, xhr.response));\n };\n\n if(statData != null){\n xhr.upload.addEventListener(\"progress\", (data: ProgressEvent) => {\n if(data.lengthComputable){\n statData.loaded = data.loaded;\n statData.total = data.total;\n statData.end = new Date();\n\n //TODO: Symplify this.\n if(TimeUtil.TimeToSeconds(statData.end.getTime()-statData.start.getTime()) > statData.prefferedDuration*2){\n statData.loaded = 0;\n statData.total = 0;\n statData.done = true;\n xhr.abort();\n }\n }\n });\n }\n\n try {\n xhr.send(request.data);\n } catch(e){\n console.error(\"An error occured while sending.\", e);\n }\n\n });\n }\n\n /**\n * Method that takes raw information to build a Request object.\n * @param method\n * @param url\n * @param data\n * @param headers\n * @returns {Request}\n * @constructor\n */\n static CreateRequest(\n method: string,\n url: string,\n data: any = null,\n headers: any = null\n ): Request {\n\n let headerList: Header[] = [];\n for(let prop in headers){\n if(headers.hasOwnProperty(prop)){\n headerList.push(new Header(prop, headers[prop]));\n }\n }\n\n return new Request(method, url, data, headerList)\n }\n \n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/http/http.service.ts","/**\n * Created by kfaulhaber on 26/07/2017.\n *\n * Status enum for setting the status of a custom Response\n *\n */\n\n\nexport enum Status {\n Neutral = 0,\n Rejected,\n Resolved\n}\n\n\n// WEBPACK FOOTER //\n// ./src/enums/status.enum.ts","/**\n * Created by kfaulhaber on 17/07/2017.\n */\n\n\nexport class TimeUtil {\n\n /**\n * TimeToSeconds method that converts miliseconds to seconds\n * @param time\n * @returns {number}\n * @constructor\n */\n static TimeToSeconds(time: number): number {\n return time/1000;\n }\n\n /**\n * TimeToString method that takes a time and converts it to a string.\n * @param time\n * @returns {string}\n * @constructor\n */\n static TimeToString(time: number): string {\n let date = new Date(null);\n date.setTime(time);\n return date.toISOString().substr(11, 8);\n }\n\n /**\n * MilisecondsToString method that converts miliseconds to a string time format. HH:MM:SS\n * @param miliseconds\n * @returns {string}\n * @constructor\n */\n static MilisecondsToString(miliseconds: number): string {\n let seconds = TimeUtil.TimeToSeconds(miliseconds);\n let date = new Date(null);\n date.setSeconds(seconds);\n return date.toISOString().substr(11, 8);\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/utils/utils.ts","/**\n * Created by Kfaulhaber on 30/06/2017.\n *\n * Basic route creater\n *\n */\n\nexport const VIMEO_ROUTES = {\n DEFAULT: (uri:string = \"\")=>`https://api.vimeo.com${uri}`,\n TICKET: ()=>`${VIMEO_ROUTES.DEFAULT()}/me/videos`,\n VIDEOS: (videoId: number)=>`${VIMEO_ROUTES.DEFAULT(`/videos/${videoId}`)}`\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/routes/routes.ts","/**\n * Created by kfaulhaber on 13/07/2017.\n */\n\nexport const DEFAULT_VALUES = {\n preferredUploadDuration: 20,\n chunkSize: 1024*1024,\n token: \"TOKEN_STRING_HERE\", //Required\n supportedFiles: [\"mov\", \"mpeg4\", \"mp4\", \"avi\", \"wmv\", \"mpegps\", \"flv\", \"3gpp\", \"webm\"],\n name: \"\",\n description: \"\",\n file: null, //Required\n upgrade_to_1080: false,\n timeInterval: 150,\n maxAcceptedFails: 20,\n maxAcceptedUploadDuration: 60,\n useDefaultFileName: false,\n retryTimeout: 5000,\n videoData: {} //See link for a full list of supported metaData | https://developer.vimeo.com/api/endpoints/videos#PATCH/videos/{video_id}\n};\n\n\nexport const DEFAULT_EVENTS = {\n chunkprogresschanged: (event: CustomEvent)=>console.log(`Default: Chunk Progress Update: ${event.detail}/100`),\n totalprogresschanged: (event: CustomEvent)=>console.log(`Default: Total Progress Update: ${event.detail}/100`),\n vimeouploaderror: ()=>{},\n vimeouploadcomplete: ()=>{}\n};\n\n\n// WEBPACK FOOTER //\n// ./src/config/config.ts","import {DEFAULT_EVENTS} from \"../../config/config\";\n/**\n * Created by kfaulhaber on 17/07/2017.\n *\n * EventService class\n *\n * Composed of static methods for handly events\n *\n */\n\nexport class EventService {\n\n /**\n * Add static method that registers a valid event name.\n * @param eventName\n * @param callback\n * @constructor\n */\n public static Add(eventName: string, callback: any){\n window.addEventListener(eventName, callback, false);\n }\n\n /**\n * Remove static method that unregisters a listener with a valid event name\n * @param eventName\n * @param callback\n * @constructor\n */\n public static Remove(eventName: string, callback: any){\n window.removeEventListener(eventName, callback, false);\n }\n\n /**\n * Dispatch static method that emits an event\n * @param eventName\n * @param data\n * @constructor\n */\n public static Dispatch(eventName: string, data: any = null){\n let customEvent = new CustomEvent(eventName, {detail: data});\n window.dispatchEvent(customEvent);\n }\n\n /**\n * Exists static method that checks if an event name is valid.\n * @param eventName\n * @returns {boolean}\n * @constructor\n */\n public static Exists(eventName: string): boolean{\n return DEFAULT_EVENTS.hasOwnProperty(eventName);\n }\n\n /**\n * GetDefault static method that returns the default handler for a given event.\n * @param eventName\n * @returns {any}\n * @constructor\n */\n public static GetDefault(eventName: string): any {\n return DEFAULT_EVENTS[eventName];\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/event/event.service.ts","import {App} from \"./app\";\nvar module;\n/**\n * Created by kfaulhaber on 30/06/2017.\n */\n\n/**\n * Binding library to exports\n * @type {App}\n */\nmodule.exports = App;\n\n\n// WEBPACK FOOTER //\n// ./src/main.ts","import {TicketService} from \"./services/ticket/ticket.service\";\nimport {ChunkService} from \"./services/chunk/chunk.service\";\nimport {UploadService} from \"./services/upload/upload.service\";\nimport {DEFAULT_VALUES} from \"./config/config\";\nimport {EventService} from \"./services/event/event.service\";\nimport {ValidatorService} from \"./services/validator/validator.service\";\nimport {MediaService} from \"./services/media/media.service\";\nimport {Response} from \"./entities/response\";\nimport {HttpService} from \"./services/http/http.service\";\nimport {StatService} from \"./services/stat/stat.service\";\nimport {Header} from \"./entities/header\";\n\nexport class App {\n\n //Defining all services\n private ticketService: TicketService;\n private chunkService: ChunkService;\n private uploadService: UploadService;\n private validatorService: ValidatorService;\n private mediaService: MediaService;\n private statService: StatService;\n private httpService: HttpService;\n\n //Defining other properties\n private failCount: number = 0;\n private maxAcceptedFails: number;\n private retryTimeout: number;\n\n /**\n * Method that initializes the VimeoUpload library. Called everytime an upload is started.\n * Resets all the services and properties. To see \"config/config.ts\" for all properties that can be added to options.\n * @param options\n */\n public init(options: any = {}){\n\n let values: any = {};\n\n //We loop through all the default values and see if options overides specific ones. All new properties are added to values object.\n for(let prop in DEFAULT_VALUES){\n if(DEFAULT_VALUES.hasOwnProperty(prop)){\n values[prop] = (options.hasOwnProperty(prop)) ? options[prop]: DEFAULT_VALUES[prop];\n }\n }\n\n this.maxAcceptedFails = values.maxAcceptedFails;\n this.httpService = new HttpService(\n values.maxAcceptedUploadDuration\n );\n this.mediaService = new MediaService(\n this.httpService,\n values.file,\n values.videoData,\n values.upgrade_to_1080,\n values.useDefaultFileName\n );\n this.chunkService = new ChunkService(\n this.mediaService,\n values.preferredUploadDuration,\n values.chunkSize\n );\n this.statService = new StatService(\n values.timeInterval,\n this.chunkService\n );\n this.ticketService = new TicketService(\n values.token,\n this.httpService,\n values.upgrade_to_1080\n );\n this.uploadService = new UploadService(\n this.mediaService,\n this.ticketService,\n this.httpService,\n this.statService\n );\n this.validatorService = new ValidatorService(\n values.supportedFiles\n );\n }\n\n /**\n * Start method that'll initiate the upload, create the upload ticket and start the upload loop.\n * @param options\n */\n public start(options: any = {}){\n this.init(options);\n\n //TODO: Add error if not supported.\n\n if(!this.validatorService.isSupported(this.mediaService.media.file)) return;\n this.ticketService.open()\n .then((response: Response)=>{\n console.log(response);\n this.ticketService.save(response);\n this.statService.start();\n this.process();\n }).catch((error)=>{\n if(this.canContinue()){\n this.failCount++;\n EventService.Dispatch(\"vimeouploaderror\", { message:`Error creating ticket.`, error});\n setTimeout(()=>{\n this.start(options);\n }, this.retryTimeout);\n }\n });\n }\n\n\n\n /**\n * Process method that will seek the next chunk to upload\n */\n private process(){\n let chunk = this.chunkService.create();\n this.uploadService.send(chunk).then((response: Response) => {\n this.chunkService.updateSize(this.statService.getChunkUploadDuration());\n this.check();\n }).catch(error=>{\n if(this.canContinue()){\n this.failCount++;\n EventService.Dispatch(\"vimeouploaderror\", { message:`Error sending chunk.`, error});\n this.chunkService.updateSize(this.statService.getChunkUploadDuration());\n setTimeout(()=>{\n this.check();\n }, this.retryTimeout);\n }\n });\n }\n\n /**\n * Check method that is called after each chunk upload to update the byte range.\n */\n private check(){\n this.uploadService.getRange().then((response: Response) => {\n switch(response.status){\n case 308:\n\n //noinspection TypeScriptValidateTypes\n let range: Header = response.responseHeaders.find((header: Header) => {\n if(header === null && header === undefined) return false;\n return header.title === \"Range\";\n });\n\n this.chunkService.updateOffset(range.value);\n if(this.chunkService.isDone()){\n this.done();\n return;\n }\n this.process();\n break;\n case 200 || 201:\n this.done();\n break;\n default:\n console.warn(`Unrecognized status code (${response.status}) for chunk range.`)\n }\n }).catch(error=>{\n EventService.Dispatch(\"vimeouploaderror\", { message: `Unable to get range.`, error});\n if(this.canContinue()){\n this.failCount++;\n setTimeout(()=>{\n this.check();\n }, this.retryTimeout);\n }\n\n })\n }\n\n /**\n * Done method that is called when an upload has been completed. Closes the upload ticket.\n */\n private done(){\n this.statService.totalStatData.done = true;\n this.ticketService.close().then((response: Response)=>{\n this.statService.stop();\n try{\n //noinspection TypeScriptValidateTypes\n let vimeoId: number = parseInt(response.responseHeaders.find((header: Header) => {\n //noinspection TypeScriptValidateTypes\n if(header === null && header === undefined) return false;\n return header.title === \"Location\";\n }).value.replace(\"/videos/\", \"\"));\n this.updateVideo(vimeoId);\n\n }catch(error){\n console.log(`Error retrieving Vimeo Id.`);\n }\n\n console.log(`Delete success:`, response);\n }).catch((error)=>{\n this.statService.stop();\n EventService.Dispatch(\"vimeouploaderror\", { message:`Unable to close upload ticket.`, error});\n });\n }\n\n /**\n * UpdateVideo method\n * @param vimeoId\n */\n private updateVideo(vimeoId: number){\n this.mediaService.updateVideoData(this.ticketService.token, vimeoId).then((response: Response) => {\n let meta = MediaService.GetMeta(vimeoId, response.data);\n EventService.Dispatch(\"vimeouploadcomplete\", meta);\n }).catch(error=>{\n EventService.Dispatch(\"vimeouploaderror\", { message: `Unable to update video ${vimeoId} with name and description.`, error})\n });\n }\n\n /**\n * on method to add a listener. See config/config.ts for a list of available events\n * @param eventName\n * @param callback\n */\n public on(eventName: string, callback: any = null){\n if(!EventService.Exists(eventName)) return;\n if(callback === null){\n callback = EventService.GetDefault(eventName);\n }\n EventService.Add(eventName, callback);\n }\n\n /**\n * off method to remove a listener. See config/config.ts for a list of available events\n * @param eventName\n * @param callback\n */\n public off(eventName: string, callback: any = null){\n if(!EventService.Exists(eventName)) return;\n if(callback === null){\n callback = EventService.GetDefault(eventName);\n }\n EventService.Remove(eventName, callback)\n }\n\n /**\n * canContinue method checks to see if the amount of failCounts exceed the maxAcceptedFails\n * @returns {boolean}\n */\n private canContinue(): boolean {\n return (this.maxAcceptedFails === 0) ? true : (this.failCount <= this.maxAcceptedFails) ? true : false;\n }\n \n}\n\n\n// WEBPACK FOOTER //\n// ./src/app.ts","import {HttpService} from \"../http/http.service\";\nimport {Ticket} from \"../../entities/ticket\";\nimport {Response} from \"../../entities/response\";\nimport {VIMEO_ROUTES} from \"../../routes/routes\";\nimport {Status} from \"../../enums/status.enum\";\n/**\n * Created by kfaulhaber on 30/06/2017.\n */\n\nexport class TicketService {\n\n public ticket:Ticket;\n\n /**\n * constructor that takes 3 paramaters\n * @param token\n * @param httpService\n * @param upgrade_to_1080\n */\n constructor(\n public token: string,\n public httpService: HttpService,\n public upgrade_to_1080: boolean\n ){}\n\n /**\n * open method that creates a ticket request\n * @returns {Promise}\n */\n public open(): Promise {\n\n let data = { type: 'streaming' };\n\n if(this.upgrade_to_1080){\n data[\"upgrade_to_1080\"] = this.upgrade_to_1080;\n }\n\n let request = HttpService.CreateRequest(\"POST\", VIMEO_ROUTES.TICKET(), JSON.stringify(data), {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json'\n });\n\n return this.httpService.send(request);\n }\n\n /**\n * save method that takes a response from creating a ticket upload request and saves it\n * @param response\n */\n public save(response: Response){\n this.ticket = new Ticket(\n response.data.upload_link_secure,\n response.data.ticket_id,\n response.data.upload_link,\n response.data.complete_uri,\n response.data.user\n );\n }\n\n /**\n * close method that sends a DELETE request to the ticket's complete Uri to complete and finalize the upload.\n * Called at the end of the upload when all the bytes have been sent.\n * @returns {Promise}\n */\n public close(): Promise{\n let request = HttpService.CreateRequest(\"DELETE\", VIMEO_ROUTES.DEFAULT(this.ticket.completeUri), null, {\n Authorization: `Bearer ${this.token}`\n });\n return this.httpService.send(request)\n }\n}\n\n\n\n\n// WEBPACK FOOTER //\n// ./src/services/ticket/ticket.service.ts","import {Header} from \"./header\";\n/**\n * Created by kfaulhaber on 17/07/2017.\n *\n * Custom Request Entity\n *\n */\n\n\nexport class Request {\n\n constructor(\n public method: string,\n public url: string,\n public data: any = null,\n public headers: Header[] = []\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/request.ts","/**\n * Created by kfaulhaber on 24/07/2017.\n *\n * Header Class Entity\n */\n\nexport class Header {\n constructor(\n public title: string,\n public value: string\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/header.ts","import {Status} from \"../enums/status.enum\";\nimport {Header} from \"./header\";\n/**\n * Created by kfaulhaber on 20/07/2017.\n *\n * Custom Response Entity\n *\n */\n\nexport class Response {\n\n public responseHeaders: Header[];\n public statusCode: Status = Status.Neutral;\n\n constructor(\n public status: number,\n public statusText: string,\n public data: any = null\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/response.ts","/**\n * Created by kfaulhaber on 13/07/2017.\n *\n * Ticket Entity\n *\n */\n\nexport class Ticket {\n constructor(\n public uploadLinkSecure: string,\n public ticketId: string,\n public uploadLink: string,\n public completeUri: string,\n public user: any\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/ticket.ts","import {Chunk} from \"../../entities/chunk\";\nimport {MediaService} from \"../media/media.service\";\n/**\n * Created by kfaulhaber on 30/06/2017.\n */\n\nexport class ChunkService {\n\n private static Adjuster: number = 0.7;\n\n /**\n * constructor\n * @param mediaService\n * @param preferredUploadDuration\n * @param size\n * @param offset\n */\n constructor(\n public mediaService: MediaService,\n public preferredUploadDuration:number,\n public size:number,\n public offset: number = 0\n ){}\n\n /**\n * updateSize method that updates the next chunk size based on the uploadDuration compares to the prefferedUploadDuration\n * @param uploadDuration\n */\n public updateSize(uploadDuration: number) {\n this.size = Math.floor((this.size*this.preferredUploadDuration)/uploadDuration*ChunkService.Adjuster);\n }\n\n /**\n * create method that returns the next chunk to upload from the byte array\n * @returns {Chunk}\n */\n public create(): Chunk{\n let end = Math.min(this.offset + this.size, this.mediaService.media.file.size);\n\n //TODO: Simplify\n if(end-this.offset !== this.size){\n this.updateSize(end-this.offset);\n }\n\n let content = this.mediaService.media.file.slice(this.offset, end);\n\n return new Chunk(\n content,\n `bytes ${this.offset}-${end}/${this.mediaService.media.file.size}`\n )\n }\n\n /**\n * updateOffset method that takes a range and updates the offset.\n * @param range\n */\n public updateOffset(range: string){\n this.offset = parseInt(range.match(/\\d+/g).pop(), 10) + 1;\n }\n\n /**\n * isDone method that checks to see if the offset is or is superior to the file size.\n * @returns {boolean}\n */\n public isDone(): boolean {\n return this.offset >= this.mediaService.media.file.size;\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/chunk/chunk.service.ts","/**\n * Created by kfaulhaber on 13/07/2017.\n *\n * Chunk Entity\n *\n */\n\n\nexport class Chunk {\n constructor(\n public content: Blob,\n public contentRange: string\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/chunk.ts","import {Chunk} from \"../../entities/chunk\";\nimport {HttpService} from \"../http/http.service\";\nimport {TicketService} from \"../ticket/ticket.service\";\nimport {MediaService} from \"../media/media.service\";\nimport {StatService} from \"../stat/stat.service\";\nimport {Status} from \"../../enums/status.enum\";\nimport {Response} from \"../../entities/response\";\n/**\n * Created by kfaulhaber on 30/06/2017.\n */\n\n\nexport class UploadService {\n\n /**\n * constructor that has mulitple dependencies to other services\n * @param mediaService\n * @param ticketService\n * @param httpService\n * @param statService\n */\n constructor(\n public mediaService: MediaService,\n public ticketService: TicketService,\n public httpService: HttpService,\n public statService: StatService\n ){}\n\n /**\n * Method that sends a request with the video chunk data\n * @param chunk\n * @returns {Promise}\n */\n public send(chunk: Chunk): Promise{\n\n let statData = this.statService.create();\n this.statService.save(statData);\n let request = HttpService.CreateRequest(\"PUT\", this.ticketService.ticket.uploadLinkSecure, chunk.content, {\n 'Content-Type': this.mediaService.media.file.type,\n 'Content-Range': chunk.contentRange\n });\n\n return this.httpService.send(request, statData);\n }\n\n /**\n * getRange method that gets the byte range of the already uploaded video content\n * @returns {Promise}\n */\n public getRange(): Promise{\n let request = HttpService.CreateRequest(\"PUT\", this.ticketService.ticket.uploadLinkSecure, null, {\n 'Content-Type': this.mediaService.media.file.type,\n 'Content-Range': 'bytes */* '\n });\n return this.httpService.send(request);\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/upload/upload.service.ts","/**\n * Created by kfaulhaber on 30/06/2017.\n */\n\nexport class ValidatorService {\n\n /**\n * constructor that takes in a list of supported video files\n * @param supportedFiles\n */\n constructor(\n public supportedFiles: string[]\n ){}\n\n /**\n * Method that takes a file and decides whether it's supported\n * @param file\n * @returns {boolean}\n */\n public isSupported(file: File) {\n let type = file.type;\n\n if(type.indexOf('/') === -1){\n console.warn(`Wrong type found (${type}).`);\n return false;\n }\n\n let split = type.split('/');\n\n if(split[0] !== \"video\"){\n console.warn(`Only videos are supported, ${type} given.`)\n return false;\n }\n\n return this.supportedFiles.includes(split[1]);\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/validator/validator.service.ts","import {Media} from \"../../entities/media\";\nimport {HttpService} from \"../http/http.service\";\nimport {VIMEO_ROUTES} from \"../../routes/routes\";\n/**\n * Created by kfaulhaber on 21/07/2017.\n */\n\nexport class MediaService {\n\n public media: Media;\n\n /**\n * constructor that initiates the services with the list of dependencies\n * @param httpService\n * @param file\n * @param data\n * @param upgrade_to_1080\n * @param useDefaultFileName\n */\n constructor(\n public httpService: HttpService,\n file: File,\n data: any,\n upgrade_to_1080: boolean,\n useDefaultFileName: boolean\n ){\n if(useDefaultFileName){\n data[\"name\"] = file.name;\n }\n this.media = new Media(file, data, upgrade_to_1080);\n }\n\n /**\n * updateVideoData method that sends a request to edit video information.\n * Will not work if the token does not have the \"EDIT\" scope. Will return a 403 forbidden.\n * @param {string} token\n * @param {number} vimeoId\n * @returns {Promise}\n */\n public updateVideoData(token: string, vimeoId: number): Promise{\n\n let params = this.media.data;\n let query = Object.keys(params).map(key=>`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`).join('&');\n console.log(query);\n let request = HttpService.CreateRequest(\"PATCH\", VIMEO_ROUTES.VIDEOS(vimeoId), query, {\n Authorization: `Bearer ${token}`\n });\n return this.httpService.send(request);\n }\n\n /**\n * GetMeta static method returns an object with data from updateVideoData response\n * @param {number} vimeoId\n * @param {object} data\n * @returns {{id: number, link: (any|HTMLLinkElement|(function(string): string)), name: any, uri: any, createdTime: any}}\n */\n public static GetMeta(vimeoId: number, data: any): Object{\n return {\n id: vimeoId,\n link: data.link,\n name: data.name,\n uri: data.uri,\n createdTime: data.created_time\n };\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/media/media.service.ts","/**\n * Created by kfaulhaber on 20/07/2017.\n */\n\nexport class Media {\n\n /**\n * constructor\n * @param file\n * @param data\n * @param upgrade_to_1080\n */\n\n constructor(\n public file: File,\n public data: any,\n public upgrade_to_1080: boolean\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/media.ts","import {EventService} from \"../event/event.service\";\nimport {TimeUtil} from \"../../utils/utils\";\nimport {ChunkService} from \"../chunk/chunk.service\";\nimport {StatData} from \"../../entities/stat_data\";\n/**\n * Created by Grimbode on 14/07/2017.\n *\n * Service that takes care of checking the total uploaded content and dispatches events to notify all listeners.\n *\n */\n\nexport class StatService {\n\n public si: number = -1;\n public totalStatData: StatData;\n public chunkStatData: StatData;\n public previousTotalPercent: number = 0;\n\n /**\n * constructor that takes two dependencies timerInterval and chunkService\n * @param timeInterval\n * @param chunkService\n */\n constructor(\n public timeInterval: number,\n public chunkService: ChunkService\n ){}\n\n /**\n * start method that starts the interval loop to constantly dispatch events with updated information.\n */\n public start(){\n this.totalStatData = this.create(true);\n this.startInterval();\n }\n\n /**\n * create method creates a new statData with information from chunkservice.\n * @param isTotal\n * @returns {StatData}\n */\n public create(isTotal: boolean = false): StatData {\n let date = new Date();\n let size = (isTotal) ? this.chunkService.mediaService.media.file.size : this.chunkService.size;\n let statData = new StatData(date, date, this.chunkService.preferredUploadDuration, 0, size);\n return statData;\n }\n\n /**\n * save method that takes a statData and saves it to the chunkStatData\n * @param timeData\n */\n public save(timeData: StatData){\n this.chunkStatData = timeData;\n }\n\n /**\n * calculateRatio method that calculates the decimal percent of how much has been uploaded (can be chunk or total)\n * @param loaded\n * @param total\n * @returns {number}\n */\n public calculateRatio(loaded: number, total: number): number{\n return loaded/total;\n }\n\n /**\n * calculatePercent method calculates the percent that has been uploaded.\n * @param loaded\n * @param total\n * @returns {number}\n */\n public calculatePercent(loaded: number, total: number): number{\n return Math.floor(this.calculateRatio(loaded, total)*100);\n }\n\n /**\n * updateTotal method that updates the total percent that has currently been uploaded.\n */\n public updateTotal(){\n this.totalStatData.loaded += this.chunkStatData.total;\n }\n\n /**\n * startInterval method that starts the interval loop to continously dispatch events with updated information on what has been uploaded.\n */\n public startInterval(){\n if(this.si > -1){\n this.stop();\n }\n\n this.si = setInterval(()=>{\n\n let chunkPercent = this.calculatePercent(this.chunkStatData.loaded, this.chunkStatData.total);\n if(this.chunkStatData.done){\n this.updateTotal();\n this.chunkStatData.total = this.chunkStatData.loaded = 0;\n chunkPercent = 100;\n }\n\n this.totalStatData.loaded = Math.max(this.chunkService.offset, this.totalStatData.loaded);\n\n this.totalStatData.end = this.chunkStatData.end;\n this.previousTotalPercent = Math.max(this.totalStatData.loaded + this.chunkStatData.loaded, this.previousTotalPercent);\n\n\n let totalPercent = this.calculatePercent(\n this.previousTotalPercent,\n this.totalStatData.total\n );\n \n EventService.Dispatch(\"chunkprogresschanged\", chunkPercent);\n\n if(this.totalStatData.done){\n totalPercent = 100;\n }\n\n EventService.Dispatch(\"totalprogresschanged\", totalPercent);\n\n }, this.timeInterval)\n\n }\n\n /**\n * stop method that stops the interval loop, which will stop the flow of dispatched events.\n */\n public stop(){\n clearInterval(this.si);\n }\n\n /**\n * getChunkUploadDuration method that returns the current time it has taken to upload a chunk.\n * @returns {number}\n */\n public getChunkUploadDuration(): number{\n return TimeUtil.TimeToSeconds(this.chunkStatData.end.getTime() - this.chunkStatData.start.getTime());\n }\n\n /**\n * chunkIsOverPrefferedUploadTime method that checks if the duration time has exceeded the preffered upload duration.\n * @returns {boolean}\n */\n public chunkIsOverPrefferedUploadTime(): boolean{\n return this.getChunkUploadDuration() >= this.chunkService.preferredUploadDuration*1.5;\n }\n}\n\n\n// WEBPACK FOOTER //\n// ./src/services/stat/stat.service.ts","/**\n * Created by kfaulhaber on 24/07/2017.\n *\n * StatData Entity\n *\n */\n\nexport class StatData {\n constructor(\n public start: Date,\n public end: Date,\n public prefferedDuration: number,\n public loaded: number = 0,\n public total: number = 0,\n public done: boolean = false\n ){}\n}\n\n\n// WEBPACK FOOTER //\n// ./src/entities/stat_data.ts"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/vimeo-upload.min.js b/dist/vimeo-upload.min.js new file mode 100644 index 0000000..d328ba0 --- /dev/null +++ b/dist/vimeo-upload.min.js @@ -0,0 +1 @@ +var VimeoUpload=function(e){function t(n){if(i[n])return i[n].exports;var r=i[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var i={};return t.m=e,t.c=i,t.d=function(e,i,n){t.o(e,i)||Object.defineProperty(e,i,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var i=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(i,"a",i),i},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=6)}([function(e,t,i){"use strict";t.__esModule=!0;var n=i(9),r=i(10),o=i(11),a=i(2),s=i(1),u=function(){function e(e){this.maxAcceptedUploadDuration=e}return e.DefaultResolver=function(e){var t=null;try{t=JSON.parse(e.response)}catch(i){t=e.response}var i=new o.Response(e.status,e.statusText,t);return i.responseHeaders=e.getAllResponseHeaders().split("\r\n").filter(function(e){return e.length>0}).map(function(e){var t=e.indexOf(":");return new r.Header(e.slice(0,t).trim(),e.slice(t+1).trim())}),e.status>308?i.statusCode=s.Status.Rejected:i.statusCode=s.Status.Resolved,i},e.prototype.send=function(t,i){return void 0===i&&(i=null),new Promise(function(n,r){var u=new XMLHttpRequest;u.open(t.method,t.url,!0),t.headers.forEach(function(e){return u.setRequestHeader(e.title,e.value)}),u.onload=function(){null!==i&&(i.end=new Date,i.done=!0);var t=e.DefaultResolver(u);switch(!0){case t.statusCode===s.Status.Resolved:n(t);break;default:r(t)}},u.onabort=function(){r(new o.Response(u.status,u.statusText,u.response))},u.onerror=function(){r(new o.Response(u.status,u.statusText,u.response))},null!=i&&u.upload.addEventListener("progress",function(e){e.lengthComputable&&(i.loaded=e.loaded,i.total=e.total,i.end=new Date,a.TimeUtil.TimeToSeconds(i.end.getTime()-i.start.getTime())>2*i.prefferedDuration&&(i.loaded=0,i.total=0,i.done=!0,u.abort()))});try{u.send(t.data)}catch(e){console.error("An error occured while sending.",e)}})},e.CreateRequest=function(e,t,i,o){void 0===i&&(i=null),void 0===o&&(o=null);var a=[];for(var s in o)o.hasOwnProperty(s)&&a.push(new r.Header(s,o[s]));return new n.Request(e,t,i,a)},e}();t.HttpService=u},function(e,t,i){"use strict";t.__esModule=!0;!function(e){e[e.Neutral=0]="Neutral",e[e.Rejected=1]="Rejected",e[e.Resolved=2]="Resolved"}(t.Status||(t.Status={}))},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(){}return e.TimeToSeconds=function(e){return e/1e3},e.TimeToString=function(e){var t=new Date(null);return t.setTime(e),t.toISOString().substr(11,8)},e.MilisecondsToString=function(t){var i=e.TimeToSeconds(t),n=new Date(null);return n.setSeconds(i),n.toISOString().substr(11,8)},e}();t.TimeUtil=n},function(e,t,i){"use strict";t.__esModule=!0,t.VIMEO_ROUTES={DEFAULT:function(e){return void 0===e&&(e=""),"https://api.vimeo.com"+e},TICKET:function(){return t.VIMEO_ROUTES.DEFAULT()+"/me/videos"},VIDEOS:function(e){return""+t.VIMEO_ROUTES.DEFAULT("/videos/"+e)}}},function(e,t,i){"use strict";t.__esModule=!0,t.DEFAULT_VALUES={preferredUploadDuration:20,chunkSize:1048576,token:"TOKEN_STRING_HERE",supportedFiles:["mov","mpeg4","mp4","avi","wmv","mpegps","flv","3gpp","webm"],name:"",description:"",file:null,upgrade_to_1080:!1,timeInterval:150,maxAcceptedFails:20,maxAcceptedUploadDuration:60,useDefaultFileName:!1,retryTimeout:5e3,videoData:{}},t.DEFAULT_EVENTS={chunkprogresschanged:function(e){return console.log("Default: Chunk Progress Update: "+e.detail+"/100")},totalprogresschanged:function(e){return console.log("Default: Total Progress Update: "+e.detail+"/100")},vimeouploaderror:function(){},vimeouploadcomplete:function(){}}},function(e,t,i){"use strict";t.__esModule=!0;var n=i(4),r=function(){function e(){}return e.Add=function(e,t){window.addEventListener(e,t,!1)},e.Remove=function(e,t){window.removeEventListener(e,t,!1)},e.Dispatch=function(e,t){void 0===t&&(t=null);var i=new CustomEvent(e,{detail:t});window.dispatchEvent(i)},e.Exists=function(e){return n.DEFAULT_EVENTS.hasOwnProperty(e)},e.GetDefault=function(e){return n.DEFAULT_EVENTS[e]},e}();t.EventService=r},function(e,t,i){"use strict";t.__esModule=!0;var e,n=i(7);e.exports=n.App},function(e,t,i){"use strict";t.__esModule=!0;var n=i(8),r=i(13),o=i(15),a=i(4),s=i(5),u=i(16),c=i(17),d=i(0),l=i(19),p=function(){function e(){this.failCount=0}return e.prototype.init=function(e){void 0===e&&(e={});var t={};for(var i in a.DEFAULT_VALUES)a.DEFAULT_VALUES.hasOwnProperty(i)&&(t[i]=e.hasOwnProperty(i)?e[i]:a.DEFAULT_VALUES[i]);this.maxAcceptedFails=t.maxAcceptedFails,this.httpService=new d.HttpService(t.maxAcceptedUploadDuration),this.mediaService=new c.MediaService(this.httpService,t.file,t.videoData,t.upgrade_to_1080,t.useDefaultFileName),this.chunkService=new r.ChunkService(this.mediaService,t.preferredUploadDuration,t.chunkSize),this.statService=new l.StatService(t.timeInterval,this.chunkService),this.ticketService=new n.TicketService(t.token,this.httpService,t.upgrade_to_1080),this.uploadService=new o.UploadService(this.mediaService,this.ticketService,this.httpService,this.statService),this.validatorService=new u.ValidatorService(t.supportedFiles)},e.prototype.start=function(e){var t=this;void 0===e&&(e={}),this.init(e),this.validatorService.isSupported(this.mediaService.media.file)&&this.ticketService.open().then(function(e){console.log(e),t.ticketService.save(e),t.statService.start(),t.process()}).catch(function(i){t.canContinue()&&(t.failCount++,s.EventService.Dispatch("vimeouploaderror",{message:"Error creating ticket.",error:i}),setTimeout(function(){t.start(e)},t.retryTimeout))})},e.prototype.process=function(){var e=this,t=this.chunkService.create();this.uploadService.send(t).then(function(t){e.chunkService.updateSize(e.statService.getChunkUploadDuration()),e.check()}).catch(function(t){e.canContinue()&&(e.failCount++,s.EventService.Dispatch("vimeouploaderror",{message:"Error sending chunk.",error:t}),e.chunkService.updateSize(e.statService.getChunkUploadDuration()),setTimeout(function(){e.check()},e.retryTimeout))})},e.prototype.check=function(){var e=this;this.uploadService.getRange().then(function(t){switch(t.status){case 308:var i=t.responseHeaders.find(function(e){return(null!==e||void 0!==e)&&"Range"===e.title});if(e.chunkService.updateOffset(i.value),e.chunkService.isDone())return void e.done();e.process();break;case 200:e.done();break;default:console.warn("Unrecognized status code ("+t.status+") for chunk range.")}}).catch(function(t){s.EventService.Dispatch("vimeouploaderror",{message:"Unable to get range.",error:t}),e.canContinue()&&(e.failCount++,setTimeout(function(){e.check()},e.retryTimeout))})},e.prototype.done=function(){var e=this;this.statService.totalStatData.done=!0,this.ticketService.close().then(function(t){e.statService.stop();try{var i=parseInt(t.responseHeaders.find(function(e){return(null!==e||void 0!==e)&&"Location"===e.title}).value.replace("/videos/",""));e.updateVideo(i)}catch(e){console.log("Error retrieving Vimeo Id.")}console.log("Delete success:",t)}).catch(function(t){e.statService.stop(),s.EventService.Dispatch("vimeouploaderror",{message:"Unable to close upload ticket.",error:t})})},e.prototype.updateVideo=function(e){this.mediaService.updateVideoData(this.ticketService.token,e).then(function(t){var i=c.MediaService.GetMeta(e,t.data);s.EventService.Dispatch("vimeouploadcomplete",i)}).catch(function(t){s.EventService.Dispatch("vimeouploaderror",{message:"Unable to update video "+e+" with name and description.",error:t})})},e.prototype.on=function(e,t){void 0===t&&(t=null),s.EventService.Exists(e)&&(null===t&&(t=s.EventService.GetDefault(e)),s.EventService.Add(e,t))},e.prototype.off=function(e,t){void 0===t&&(t=null),s.EventService.Exists(e)&&(null===t&&(t=s.EventService.GetDefault(e)),s.EventService.Remove(e,t))},e.prototype.canContinue=function(){return 0===this.maxAcceptedFails||this.failCount<=this.maxAcceptedFails},e}();t.App=p},function(e,t,i){"use strict";t.__esModule=!0;var n=i(0),r=i(12),o=i(3),a=function(){function e(e,t,i){this.token=e,this.httpService=t,this.upgrade_to_1080=i}return e.prototype.open=function(){var e={type:"streaming"};this.upgrade_to_1080&&(e.upgrade_to_1080=this.upgrade_to_1080);var t=n.HttpService.CreateRequest("POST",o.VIMEO_ROUTES.TICKET(),JSON.stringify(e),{Authorization:"Bearer "+this.token,"Content-Type":"application/json"});return this.httpService.send(t)},e.prototype.save=function(e){this.ticket=new r.Ticket(e.data.upload_link_secure,e.data.ticket_id,e.data.upload_link,e.data.complete_uri,e.data.user)},e.prototype.close=function(){var e=n.HttpService.CreateRequest("DELETE",o.VIMEO_ROUTES.DEFAULT(this.ticket.completeUri),null,{Authorization:"Bearer "+this.token});return this.httpService.send(e)},e}();t.TicketService=a},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t,i,n){void 0===i&&(i=null),void 0===n&&(n=[]),this.method=e,this.url=t,this.data=i,this.headers=n}return e}();t.Request=n},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t){this.title=e,this.value=t}return e}();t.Header=n},function(e,t,i){"use strict";t.__esModule=!0;var n=i(1),r=function(){function e(e,t,i){void 0===i&&(i=null),this.status=e,this.statusText=t,this.data=i,this.statusCode=n.Status.Neutral}return e}();t.Response=r},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t,i,n,r){this.uploadLinkSecure=e,this.ticketId=t,this.uploadLink=i,this.completeUri=n,this.user=r}return e}();t.Ticket=n},function(e,t,i){"use strict";t.__esModule=!0;var n=i(14),r=function(){function e(e,t,i,n){void 0===n&&(n=0),this.mediaService=e,this.preferredUploadDuration=t,this.size=i,this.offset=n}return e.prototype.updateSize=function(t){this.size=Math.floor(this.size*this.preferredUploadDuration/t*e.Adjuster)},e.prototype.create=function(){var e=Math.min(this.offset+this.size,this.mediaService.media.file.size);e-this.offset!==this.size&&this.updateSize(e-this.offset);var t=this.mediaService.media.file.slice(this.offset,e);return new n.Chunk(t,"bytes "+this.offset+"-"+e+"/"+this.mediaService.media.file.size)},e.prototype.updateOffset=function(e){this.offset=parseInt(e.match(/\d+/g).pop(),10)+1},e.prototype.isDone=function(){return this.offset>=this.mediaService.media.file.size},e.Adjuster=.7,e}();t.ChunkService=r},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t){this.content=e,this.contentRange=t}return e}();t.Chunk=n},function(e,t,i){"use strict";t.__esModule=!0;var n=i(0),r=function(){function e(e,t,i,n){this.mediaService=e,this.ticketService=t,this.httpService=i,this.statService=n}return e.prototype.send=function(e){var t=this.statService.create();this.statService.save(t);var i=n.HttpService.CreateRequest("PUT",this.ticketService.ticket.uploadLinkSecure,e.content,{"Content-Type":this.mediaService.media.file.type,"Content-Range":e.contentRange});return this.httpService.send(i,t)},e.prototype.getRange=function(){var e=n.HttpService.CreateRequest("PUT",this.ticketService.ticket.uploadLinkSecure,null,{"Content-Type":this.mediaService.media.file.type,"Content-Range":"bytes */* "});return this.httpService.send(e)},e}();t.UploadService=r},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e){this.supportedFiles=e}return e.prototype.isSupported=function(e){var t=e.type;if(-1===t.indexOf("/"))return console.warn("Wrong type found ("+t+")."),!1;var i=t.split("/");return"video"!==i[0]?(console.warn("Only videos are supported, "+t+" given."),!1):this.supportedFiles.includes(i[1])},e}();t.ValidatorService=n},function(e,t,i){"use strict";t.__esModule=!0;var n=i(18),r=i(0),o=i(3),a=function(){function e(e,t,i,r,o){this.httpService=e,o&&(i.name=t.name),this.media=new n.Media(t,i,r)}return e.prototype.updateVideoData=function(e,t){var i=this.media.data,n=Object.keys(i).map(function(e){return encodeURIComponent(e)+"="+encodeURIComponent(i[e])}).join("&");console.log(n);var a=r.HttpService.CreateRequest("PATCH",o.VIMEO_ROUTES.VIDEOS(t),n,{Authorization:"Bearer "+e});return this.httpService.send(a)},e.GetMeta=function(e,t){return{id:e,link:t.link,name:t.name,uri:t.uri,createdTime:t.created_time}},e}();t.MediaService=a},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t,i){this.file=e,this.data=t,this.upgrade_to_1080=i}return e}();t.Media=n},function(e,t,i){"use strict";t.__esModule=!0;var n=i(5),r=i(2),o=i(20),a=function(){function e(e,t){this.timeInterval=e,this.chunkService=t,this.si=-1,this.previousTotalPercent=0}return e.prototype.start=function(){this.totalStatData=this.create(!0),this.startInterval()},e.prototype.create=function(e){void 0===e&&(e=!1);var t=new Date,i=e?this.chunkService.mediaService.media.file.size:this.chunkService.size;return new o.StatData(t,t,this.chunkService.preferredUploadDuration,0,i)},e.prototype.save=function(e){this.chunkStatData=e},e.prototype.calculateRatio=function(e,t){return e/t},e.prototype.calculatePercent=function(e,t){return Math.floor(100*this.calculateRatio(e,t))},e.prototype.updateTotal=function(){this.totalStatData.loaded+=this.chunkStatData.total},e.prototype.startInterval=function(){var e=this;this.si>-1&&this.stop(),this.si=setInterval(function(){var t=e.calculatePercent(e.chunkStatData.loaded,e.chunkStatData.total);e.chunkStatData.done&&(e.updateTotal(),e.chunkStatData.total=e.chunkStatData.loaded=0,t=100),e.totalStatData.loaded=Math.max(e.chunkService.offset,e.totalStatData.loaded),e.totalStatData.end=e.chunkStatData.end,e.previousTotalPercent=Math.max(e.totalStatData.loaded+e.chunkStatData.loaded,e.previousTotalPercent);var i=e.calculatePercent(e.previousTotalPercent,e.totalStatData.total);n.EventService.Dispatch("chunkprogresschanged",t),e.totalStatData.done&&(i=100),n.EventService.Dispatch("totalprogresschanged",i)},this.timeInterval)},e.prototype.stop=function(){clearInterval(this.si)},e.prototype.getChunkUploadDuration=function(){return r.TimeUtil.TimeToSeconds(this.chunkStatData.end.getTime()-this.chunkStatData.start.getTime())},e.prototype.chunkIsOverPrefferedUploadTime=function(){return this.getChunkUploadDuration()>=1.5*this.chunkService.preferredUploadDuration},e}();t.StatService=a},function(e,t,i){"use strict";t.__esModule=!0;var n=function(){function e(e,t,i,n,r,o){void 0===n&&(n=0),void 0===r&&(r=0),void 0===o&&(o=!1),this.start=e,this.end=t,this.prefferedDuration=i,this.loaded=n,this.total=r,this.done=o}return e}();t.StatData=n}]); \ No newline at end of file diff --git a/index.html b/index.html index 20b53dc..d507c23 100644 --- a/index.html +++ b/index.html @@ -10,31 +10,25 @@ position: relative; min-height: 100%; } - body { margin-bottom: 60px; color: #505662; } - .help { font-size: smaller; } - .page-header { padding-bottom: 18px; margin: 40px 0 12px; } - .logo { width: 100%; margin-bottom: 20px; } - .lead { font-size: 18px; margin-bottom: 12px; } - .footer { position: absolute; bottom: 0; @@ -44,39 +38,31 @@ height: 120px; color: #505662; } - .footer a.brand { color: #505662; } - .footer a.brand:hover { color: #393e46; text-decoration: none; } - .footer .container { border-top: 1px solid #eee; padding-top: 45px; } - /* Custom page CSS */ - .container { width: auto; max-width: 680px; padding: 0 15px; } - .container .text-muted { margin: 20px 0; } - #progress-container { -webkit-box-shadow: none; box-shadow: inset none; display:none; } - #drop_zone { border: 2px dashed #bbb; -moz-border-radius: 5px; @@ -88,33 +74,28 @@ color: #bbb; height:140px; } - #video-data { margin-top: 1em; font-size: 1.1em; font-weight: 500; } - /* Bragit buttons, http://websemantics.github.io/bragit/ */ .ui.bragit.button, .ui.bragit.buttons .button { background-color: #676f7e; color: #fff!important; } - .ui.bragit.label { color: #505662!important; border-color: #676f7e!important; background-color: #ffffff; } - .ui.bragit.button:focus, .ui.bragit.buttons .button:focus, .ui.bragit.button:hover, .ui.bragit.buttons .button:hover { background-color: #505662; } - .ui.bragit.labels .label:focus, .ui.bragit.label:focus, .ui.bragit.labels .label:hover, @@ -122,13 +103,12 @@ color: #505662!important; border-color: #505662!important; } - .ui.labeled .ui.button .star.icon { color: #F5CC7A!important; } - - + +