diff --git a/Readme.md b/Readme.md index 5fbc944..80dd255 100644 --- a/Readme.md +++ b/Readme.md @@ -13,7 +13,7 @@ The Chrome extension can be installed from [Chrome Web Store](https://chrome.goo npm install # Build JS -webpack +./node_modules/.bin/webpack ``` ## Deploy a new version diff --git a/dist/assets/css/style.css b/dist/assets/css/style.css index 48e8d7d..4574bab 100755 --- a/dist/assets/css/style.css +++ b/dist/assets/css/style.css @@ -4,6 +4,7 @@ height: 100px; bottom: 15%; color: white; + z-index: 1; } .amazon-subtitles-drop-files { @@ -34,4 +35,19 @@ background-color: transparent; line-height: 1.3; font-size: 2vv; -} \ No newline at end of file +} + +.amazon-subtitles-close { + position: absolute; + right: 0; + top: 0; + line-height: 1; + padding: 3px 10px; + z-index: 9999999999; +} + +.amazon-subtitles-close-icon { + display: block; + font-size: 20px; + transform: rotate(45deg); +} diff --git a/dist/assets/js/script.js b/dist/assets/js/script.js index 0cc3c60..a17eeb8 100644 --- a/dist/assets/js/script.js +++ b/dist/assets/js/script.js @@ -104,21 +104,24 @@ Object.defineProperty(exports, "__esModule", { value: true }); const FileHandler_1 = __webpack_require__(1); const SrtParserHandler_1 = __webpack_require__(2); const PlaybackHandler_1 = __webpack_require__(4); +const CloseHandler_1 = __webpack_require__(6); const View_1 = __webpack_require__(5); -const Utils_1 = __webpack_require__(7); -const RegisterHandlers_1 = __webpack_require__(8); +const Utils_1 = __webpack_require__(8); +const RegisterHandlers_1 = __webpack_require__(9); class AmazonPrimeSubtitles { onLoad(document) { const registerHandlers = new RegisterHandlers_1.RegisterHandlers(document); registerHandlers.registerHandler(FileHandler_1.FileHandler.EVENT_NAME, new FileHandler_1.FileHandler(document)); registerHandlers.registerHandler(SrtParserHandler_1.SrtParserHandler.EVENT_NAME, new SrtParserHandler_1.SrtParserHandler(document)); registerHandlers.registerHandler(PlaybackHandler_1.PlaybackHandler.EVENT_NAME, new PlaybackHandler_1.PlaybackHandler(document)); + registerHandlers.registerHandler(CloseHandler_1.CloseHandler.EVENT_NAME, new CloseHandler_1.CloseHandler(document)); const view = new View_1.View(document); view.display(); } } const amazonPrimeSubtitles = new AmazonPrimeSubtitles(); -Utils_1.Utils.onReady(amazonPrimeSubtitles.onLoad, document); +const webPlayerQuery = '.' + View_1.View.WEB_PLAYER_ELEMENT_CLASS; +Utils_1.Utils.waitForElementExists(webPlayerQuery, amazonPrimeSubtitles.onLoad, [document]); /***/ }), @@ -130,7 +133,7 @@ Utils_1.Utils.onReady(amazonPrimeSubtitles.onLoad, document); Object.defineProperty(exports, "__esModule", { value: true }); exports.FileHandler = void 0; const SrtParserHandler_1 = __webpack_require__(2); -const EventWithData_1 = __webpack_require__(6); +const EventWithData_1 = __webpack_require__(7); class FileHandler { constructor(document) { this.document = document; @@ -160,7 +163,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.SrtParserHandler = void 0; const OneSubtitle_1 = __webpack_require__(3); const PlaybackHandler_1 = __webpack_require__(4); -const EventWithData_1 = __webpack_require__(6); +const EventWithData_1 = __webpack_require__(7); class SrtParserHandler { constructor(document) { this.SECONDS_IN_HOUR = 3600; @@ -278,21 +281,22 @@ PlaybackHandler.SHOW_INTERVAL = 200; Object.defineProperty(exports, "__esModule", { value: true }); exports.View = void 0; const FileHandler_1 = __webpack_require__(1); -const EventWithData_1 = __webpack_require__(6); +const CloseHandler_1 = __webpack_require__(6); +const EventWithData_1 = __webpack_require__(7); class View { constructor(document) { this.document = document; } display() { const amazonSubtitlesElement = this.createSubtitlesElement(); - const webPlayerElemet = this.document.getElementById(View.WEB_PLAYER_ELEMENT_ID); + const webPlayerElemet = this.document.getElementsByClassName(View.WEB_PLAYER_ELEMENT_CLASS)[0]; webPlayerElemet.appendChild(amazonSubtitlesElement); } createSubtitlesElement() { const dropFilesElement = this.createDropFilesElement(); const subtitlesContentElement = this.createSubtitlesContentEleent(); const amazonSubtitlesElement = this.document.createElement("div"); - amazonSubtitlesElement.className = 'amazon-subtitles'; + amazonSubtitlesElement.className = View.AMAZON_SUBTITLES_CLASS; amazonSubtitlesElement.appendChild(dropFilesElement); amazonSubtitlesElement.appendChild(subtitlesContentElement); return amazonSubtitlesElement; @@ -301,6 +305,8 @@ class View { const dropFilesElement = this.document.createElement("div"); dropFilesElement.className = 'amazon-subtitles-drop-files'; dropFilesElement.innerHTML = 'Drag a *.srt File Here
'; + const closeElement = this.createCloseElement(); + dropFilesElement.appendChild(closeElement); const dropFileInputElement = this.document.createElement("input"); dropFileInputElement.className = 'amazon-subtitles-drop-file-input'; dropFileInputElement.type = 'file'; @@ -313,6 +319,19 @@ class View { dropFilesElement.appendChild(dropFileInputElement); return dropFilesElement; } + createCloseElement() { + const closeIconElement = this.document.createElement("span"); + closeIconElement.className = 'amazon-subtitles-close-icon'; + closeIconElement.innerHTML = '+'; + const closeElement = this.document.createElement("div"); + closeElement.className = 'amazon-subtitles-close'; + closeElement.appendChild(closeIconElement); + closeElement.addEventListener('click', () => { + const closeEvent = new EventWithData_1.EventWithData(CloseHandler_1.CloseHandler.EVENT_NAME); + this.document.dispatchEvent(closeEvent); + }); + return closeElement; + } createSubtitlesContentEleent() { const subtitlesContentElement = this.document.createElement("div"); subtitlesContentElement.className = View.SUBTITLES_CONTENT_ELEMENT_CLASS; @@ -320,8 +339,9 @@ class View { } } exports.View = View; -View.WEB_PLAYER_ELEMENT_ID = 'dv-web-player'; +View.WEB_PLAYER_ELEMENT_CLASS = 'scalingVideoContainer'; View.SUBTITLES_CONTENT_ELEMENT_CLASS = 'amazon-subtitles-content'; +View.AMAZON_SUBTITLES_CLASS = 'amazon-subtitles'; /***/ }), @@ -330,6 +350,28 @@ View.SUBTITLES_CONTENT_ELEMENT_CLASS = 'amazon-subtitles-content'; "use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CloseHandler = void 0; +const View_1 = __webpack_require__(5); +class CloseHandler { + constructor(document) { + this.document = document; + } + handle(event) { + const subtitlesContetnElement = this.document.getElementsByClassName(View_1.View.AMAZON_SUBTITLES_CLASS)[0]; + subtitlesContetnElement.remove(); + } +} +exports.CloseHandler = CloseHandler; +CloseHandler.EVENT_NAME = 'amazonPrimeSubtitlesClose'; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); exports.EventWithData = void 0; class EventWithData extends Event { @@ -338,7 +380,7 @@ exports.EventWithData = EventWithData; /***/ }), -/* 7 */ +/* 8 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -356,12 +398,25 @@ class Utils { fn(document); } } + static waitForElementExists(selector, callback, attributes) { + (function loopSearch() { + if (document.querySelector(selector) != null) { + callback(...attributes); + return; + } + else { + setTimeout(function () { + loopSearch(); + }, 1000); + } + })(); + } } exports.Utils = Utils; /***/ }), -/* 8 */ +/* 9 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; diff --git a/dist/manifest.json b/dist/manifest.json index da750eb..302b3fb 100755 --- a/dist/manifest.json +++ b/dist/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Amazon Prime Video Subtitles", "description": "Adding subtitles to Amazon Prime Video", - "version": "1.0", + "version": "1.1", "icons": { "128": "assets/images/icon_128.png" }, diff --git a/src/AmazonPrimeSubtitles.ts b/src/AmazonPrimeSubtitles.ts index b6fe873..f56ac26 100644 --- a/src/AmazonPrimeSubtitles.ts +++ b/src/AmazonPrimeSubtitles.ts @@ -1,6 +1,7 @@ import { FileHandler } from './lib/Handler/FileHandler' import { SrtParserHandler } from './lib/Handler/SrtParserHandler' import { PlaybackHandler } from './lib/Handler/PlaybackHandler' +import { CloseHandler } from './lib/Handler/CloseHandler' import { View } from './lib/View' import { Utils } from './lib/Utils' import { RegisterHandlers } from './lib/RegisterHandlers' @@ -11,6 +12,7 @@ class AmazonPrimeSubtitles { registerHandlers.registerHandler(FileHandler.EVENT_NAME, new FileHandler(document)); registerHandlers.registerHandler(SrtParserHandler.EVENT_NAME, new SrtParserHandler(document)); registerHandlers.registerHandler(PlaybackHandler.EVENT_NAME, new PlaybackHandler(document)); + registerHandlers.registerHandler(CloseHandler.EVENT_NAME, new CloseHandler(document)); const view = new View(document); view.display() @@ -18,4 +20,5 @@ class AmazonPrimeSubtitles { } const amazonPrimeSubtitles = new AmazonPrimeSubtitles() -Utils.onReady(amazonPrimeSubtitles.onLoad, document) +const webPlayerQuery = '.'+View.WEB_PLAYER_ELEMENT_CLASS +Utils.waitForElementExists(webPlayerQuery, amazonPrimeSubtitles.onLoad, [document]) diff --git a/src/lib/Handler/CloseHandler.ts b/src/lib/Handler/CloseHandler.ts new file mode 100644 index 0000000..8e94162 --- /dev/null +++ b/src/lib/Handler/CloseHandler.ts @@ -0,0 +1,19 @@ +import { EventWithData } from '../EventWithData'; +import { HandlerInterface } from './HandlerInterface'; +import { View } from '../View'; + +export class CloseHandler implements HandlerInterface { + + static readonly EVENT_NAME = 'amazonPrimeSubtitlesClose'; + + private document: HTMLDocument; + + constructor(document: HTMLDocument) { + this.document = document; + } + + handle(event: EventWithData): void { + const subtitlesContetnElement = this.document.getElementsByClassName(View.AMAZON_SUBTITLES_CLASS)[0]; + subtitlesContetnElement.remove(); + } +} diff --git a/src/lib/Utils.ts b/src/lib/Utils.ts index f32e0c9..c1d6127 100644 --- a/src/lib/Utils.ts +++ b/src/lib/Utils.ts @@ -1,11 +1,14 @@ -export class Utils { - static onReady(fn: Function, document: HTMLDocument): void { - if (/in/.test(document.readyState)) { - setTimeout(function() { - Utils.onReady(fn, document); - }, 100) - } else { - fn(document) - } +export class Utils { + static waitForElementExists(selector: string, callback: Function, attributes: Array) { + (function loopSearch() { + if (document.querySelector(selector) != null) { + callback(...attributes); + return; + } else { + setTimeout(function () { + loopSearch(); + }, 1000); + } + })(); } } diff --git a/src/lib/View.ts b/src/lib/View.ts index 667dda1..b4b7f81 100644 --- a/src/lib/View.ts +++ b/src/lib/View.ts @@ -1,4 +1,5 @@ import { FileHandler } from './Handler/FileHandler' +import { CloseHandler } from './Handler/CloseHandler' import { EventWithData } from './EventWithData' interface HTMLInputEvent extends Event { @@ -6,8 +7,9 @@ interface HTMLInputEvent extends Event { } export class View { - static readonly WEB_PLAYER_ELEMENT_ID = 'dv-web-player' + static readonly WEB_PLAYER_ELEMENT_CLASS = 'scalingVideoContainer' static readonly SUBTITLES_CONTENT_ELEMENT_CLASS = 'amazon-subtitles-content' + static readonly AMAZON_SUBTITLES_CLASS = 'amazon-subtitles' private document: HTMLDocument; @@ -17,7 +19,7 @@ export class View { public display(): void { const amazonSubtitlesElement = this.createSubtitlesElement(); - const webPlayerElemet = this.document.getElementById(View.WEB_PLAYER_ELEMENT_ID); + const webPlayerElemet = this.document.getElementsByClassName(View.WEB_PLAYER_ELEMENT_CLASS)[0]; webPlayerElemet.appendChild(amazonSubtitlesElement); } @@ -26,7 +28,7 @@ export class View { const subtitlesContentElement = this.createSubtitlesContentEleent(); const amazonSubtitlesElement = this.document.createElement("div"); - amazonSubtitlesElement.className = 'amazon-subtitles' + amazonSubtitlesElement.className = View.AMAZON_SUBTITLES_CLASS amazonSubtitlesElement.appendChild(dropFilesElement) amazonSubtitlesElement.appendChild(subtitlesContentElement) @@ -38,6 +40,9 @@ export class View { dropFilesElement.className = 'amazon-subtitles-drop-files' dropFilesElement.innerHTML = 'Drag a *.srt File Here
'; + const closeElement = this.createCloseElement(); + dropFilesElement.appendChild(closeElement); + const dropFileInputElement = this.document.createElement("input"); dropFileInputElement.className = 'amazon-subtitles-drop-file-input' dropFileInputElement.type = 'file' @@ -49,11 +54,28 @@ export class View { this.document.dispatchEvent(dropFileEvent); }); - dropFilesElement.appendChild(dropFileInputElement) + dropFilesElement.appendChild(dropFileInputElement); return dropFilesElement; } + private createCloseElement(): HTMLDivElement { + const closeIconElement = this.document.createElement("span"); + closeIconElement.className = 'amazon-subtitles-close-icon' + closeIconElement.innerHTML = '+'; + + const closeElement = this.document.createElement("div"); + closeElement.className = 'amazon-subtitles-close' + closeElement.appendChild(closeIconElement) + + closeElement.addEventListener('click', () => { + const closeEvent = new EventWithData(CloseHandler.EVENT_NAME); + this.document.dispatchEvent(closeEvent); + }); + + return closeElement; + } + private createSubtitlesContentEleent(): HTMLDivElement { const subtitlesContentElement = this.document.createElement("div"); subtitlesContentElement.className = View.SUBTITLES_CONTENT_ELEMENT_CLASS;