Compare commits
1 commit
develop
...
feature/#1
Author | SHA1 | Date | |
---|---|---|---|
Serraniel | 720aca5557 |
5
.github/workflows/auto-merge.yml
vendored
5
.github/workflows/auto-merge.yml
vendored
|
@ -1,15 +1,14 @@
|
||||||
name: auto-merge
|
name: auto-merge
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
auto-merge:
|
auto-merge:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.actor == 'dependabot[bot]'
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: ahmadnassri/action-dependabot-auto-merge@v2.3.1
|
- uses: ahmadnassri/action-dependabot-auto-merge@v2
|
||||||
with:
|
with:
|
||||||
target: minor
|
target: minor
|
||||||
github-token: ${{ secrets.PR_AUTO_MERGE }}
|
github-token: ${{ secrets.PR_AUTO_MERGE }}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "16"
|
- "14"
|
||||||
dist: trusty
|
dist: trusty
|
||||||
cache:
|
cache:
|
||||||
npm: true
|
npm: true
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
[![Travis (.org)](https://img.shields.io/travis/serraniel/aniwatchplus?style=flat-square)](https://travis-ci.org/github/Serraniel/AniwatchPlus)
|
[![Travis (.org)](https://img.shields.io/travis/serraniel/aniwatchplus?style=flat-square)](https://travis-ci.org/github/Serraniel/AniwatchPlus)
|
||||||
[![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/serraniel/aniwatchplus?style=flat-square)](https://snyk.io/test/github/Serraniel/AniwatchPlus?targetFile=package.json)
|
[![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/serraniel/aniwatchplus?style=flat-square)](https://snyk.io/test/github/Serraniel/AniwatchPlus?targetFile=package.json)
|
||||||
|
[![David](https://img.shields.io/david/serraniel/AniwatchPlus?style=flat-square)](https://david-dm.org/serraniel/aniwatchplus)
|
||||||
[![Scrutinizer code quality (GitHub/Bitbucket)](https://img.shields.io/scrutinizer/quality/g/serraniel/aniwatchplus?style=flat-square)](https://scrutinizer-ci.com/g/Serraniel/AniwatchPlus/)
|
[![Scrutinizer code quality (GitHub/Bitbucket)](https://img.shields.io/scrutinizer/quality/g/serraniel/aniwatchplus?style=flat-square)](https://scrutinizer-ci.com/g/Serraniel/AniwatchPlus/)
|
||||||
[![GitHub issues](https://img.shields.io/github/issues/serraniel/aniwatchplus?style=flat-square)](https://github.com/Serraniel/AniwatchPlus/issues)
|
[![GitHub issues](https://img.shields.io/github/issues/serraniel/aniwatchplus?style=flat-square)](https://github.com/Serraniel/AniwatchPlus/issues)
|
||||||
[![GitHub](https://img.shields.io/github/license/serraniel/aniwatchplus?style=flat-square)](https://github.com/Serraniel/AniwatchPlus/blob/develop/LICENSE)
|
[![GitHub](https://img.shields.io/github/license/serraniel/aniwatchplus?style=flat-square)](https://github.com/Serraniel/AniwatchPlus/blob/develop/LICENSE)
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
## Download
|
## Download
|
||||||
Click the badge for your browser to get to the download page:
|
Click the badge for your browser to get to the download page:
|
||||||
|
|
||||||
[![Chrome Web Store](https://img.shields.io/chrome-web-store/v/hgniihpjiioldkafogebpkbaiflmpimb?label=Google%20Chrome&logo=Google%20Chrome&style=flat-square)](https://chrome.google.com/webstore/detail/aniwatch-plus/hgniihpjiioldkafogebpkbaiflmpimb)
|
[![Chrome Web Store](https://img.shields.io/chrome-web-store/v/hgniihpjiioldkafogebpkbaiflmpimb?label=Google%20Chrome&logo=Google%20Chrome&style=flat-square)](https://chrome.google.com/webstore/detail/aniwatch-plus/hgniihpjiioldkafogebpkbaiflmpimb?hl=de)
|
||||||
[![Mozilla Add-on](https://img.shields.io/amo/v/aniwatch-plus?label=Mozilla%20Firefox&logo=Firefox&style=flat-square)](https://addons.mozilla.org/de/firefox/addon/aniwatch-plus/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search)
|
[![Mozilla Add-on](https://img.shields.io/amo/v/aniwatch-plus?label=Mozilla%20Firefox&logo=Firefox&style=flat-square)](https://addons.mozilla.org/de/firefox/addon/aniwatch-plus/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search)
|
||||||
[![GitHub release tag for opera (latest by date including pre-releases)](https://img.shields.io/github/v/release/serraniel/aniwatchplus?include_prereleases&label=Opera&logo=Opera&logoColor=red&style=flat-square)](https://addons.opera.com/de/extensions/details/aniwatch-plus/)
|
[![GitHub release tag for opera (latest by date including pre-releases)](https://img.shields.io/github/v/release/serraniel/aniwatchplus?include_prereleases&label=Opera&logo=Opera&logoColor=red&style=flat-square)](https://addons.opera.com/de/extensions/details/aniwatch-plus/)
|
||||||
[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/serraniel/aniwatchplus?include_prereleases&label=Download%20manually&logo=Github&style=flat-square)](https://github.com/Serraniel/AniwatchPlus/releases)
|
[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/serraniel/aniwatchplus?include_prereleases&label=Download%20manually&logo=Github&style=flat-square)](https://github.com/Serraniel/AniwatchPlus/releases)
|
||||||
|
|
|
@ -15,7 +15,7 @@ const { debug } = require('console');
|
||||||
|
|
||||||
const $ = gulpLoadPlugins()
|
const $ = gulpLoadPlugins()
|
||||||
|
|
||||||
const sass = require('gulp-sass')(require('sass'));
|
$.sass.compiler = require('sass');
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
Base consts
|
Base consts
|
||||||
|
@ -82,11 +82,11 @@ gulp.task('styles', () => {
|
||||||
// sourcemap initialization
|
// sourcemap initialization
|
||||||
.pipe($.if(isDev, $.sourcemaps.init()))
|
.pipe($.if(isDev, $.sourcemaps.init()))
|
||||||
// sass compilation
|
// sass compilation
|
||||||
.pipe(sass.sync({
|
.pipe($.sass.sync({
|
||||||
outputStyle: 'expanded',
|
outputStyle: 'expanded',
|
||||||
precision: 7,
|
precision: 7,
|
||||||
includePaths: ['.'],
|
includePaths: ['.'],
|
||||||
}).on('error', sass.logError))
|
}).on('error', $.sass.logError))
|
||||||
// autoprefix
|
// autoprefix
|
||||||
.pipe($.autoprefixer())
|
.pipe($.autoprefixer())
|
||||||
// out stream size
|
// out stream size
|
||||||
|
|
21481
package-lock.json
generated
21481
package-lock.json
generated
File diff suppressed because it is too large
Load diff
52
package.json
52
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aniwatch-plus",
|
"name": "aniwatch-plus",
|
||||||
"version": "1.1.0",
|
"version": "1.0.0",
|
||||||
"description": "Aniwatch Plus is a browser extension for https://aniwatch.me/",
|
"description": "Aniwatch Plus is a browser extension for https://aniwatch.me/",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -33,48 +33,48 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Serraniel/AniwatchPlus#readme",
|
"homepage": "https://github.com/Serraniel/AniwatchPlus#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^3.2.1",
|
"color": "^3.1.3",
|
||||||
"spacetime": "https://github.com/Serraniel/spacetime#bugfix/#255-typescript-constructor-options-missing",
|
"spacetime": "^6.12.3",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/compat-data": "^7.22.5",
|
"@babel/compat-data": "^7.12.13",
|
||||||
"@babel/core": "^7.22.9",
|
"@babel/core": "^7.12.13",
|
||||||
"@babel/helper-module-imports": "^7.22.5",
|
"@babel/helper-module-imports": "^7.12.13",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.17.12",
|
"@babel/plugin-proposal-private-methods": "^7.12.13",
|
||||||
"@babel/preset-env": "^7.22.9",
|
"@babel/preset-env": "^7.12.13",
|
||||||
"@babel/register": "^7.22.5",
|
"@babel/register": "^7.12.13",
|
||||||
"@types/chrome": "0.0.241",
|
"@types/chrome": "0.0.129",
|
||||||
"babelify": "^10.0.0",
|
"babelify": "^10.0.0",
|
||||||
"browserify": "^17.0.0",
|
"browserify": "^17.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cssnano": "^5.1.15",
|
"cssnano": "^4.1.10",
|
||||||
"del": "^6.1.1",
|
"del": "^6.0.0",
|
||||||
"factor-bundle": "^2.5.0",
|
"factor-bundle": "^2.5.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-autoprefixer": "^8.0.0",
|
"gulp-autoprefixer": "^7.0.1",
|
||||||
"gulp-babel": "^8.0.0",
|
"gulp-babel": "^8.0.0",
|
||||||
"gulp-if": "^3.0.0",
|
"gulp-if": "^3.0.0",
|
||||||
"gulp-imagemin": "^7.1.0",
|
"gulp-imagemin": "^7.1.0",
|
||||||
"gulp-load-plugins": "^2.0.8",
|
"gulp-load-plugins": "^2.0.6",
|
||||||
"gulp-merge": "^0.1.1",
|
"gulp-merge": "^0.1.1",
|
||||||
"gulp-plumber": "^1.2.1",
|
"gulp-plumber": "^1.2.1",
|
||||||
"gulp-postcss": "^9.0.1",
|
"gulp-postcss": "^9.0.0",
|
||||||
"gulp-rename": "^2.0.0",
|
"gulp-rename": "^2.0.0",
|
||||||
"gulp-replace": "^1.1.4",
|
"gulp-replace": "^1.0.0",
|
||||||
"gulp-sass": "^5.1.0",
|
"gulp-sass": "^4.1.0",
|
||||||
"gulp-size": "^4.0.1",
|
"gulp-size": "^3.0.0",
|
||||||
"gulp-sourcemaps": "^3.0.0",
|
"gulp-sourcemaps": "^3.0.0",
|
||||||
"gulp-terser": "^2.1.0",
|
"gulp-terser": "^2.0.1",
|
||||||
"gulp-typescript": "^6.0.0-alpha.1",
|
"gulp-typescript": "^6.0.0-alpha.1",
|
||||||
"gulp-zip": "^5.1.0",
|
"gulp-zip": "^5.0.2",
|
||||||
"merge-stream": "^2.0.0",
|
"merge-stream": "^2.0.0",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.2.4",
|
||||||
"sass": "^1.64.1",
|
"sass": "^1.32.6",
|
||||||
"terser": "^5.19.2",
|
"terser": "^5.5.1",
|
||||||
"tsify": "^5.0.4",
|
"tsify": "^5.0.2",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.1.3",
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vinyl-source-stream": "^2.0.0",
|
"vinyl-source-stream": "^2.0.0",
|
||||||
"web-ext-types": "^3.2.1"
|
"web-ext-types": "^3.2.1"
|
||||||
|
|
|
@ -44,20 +44,9 @@
|
||||||
<input type="checkbox" id="playerAutoplayAfterScreenshot" data-default-value="true" />
|
<input type="checkbox" id="playerAutoplayAfterScreenshot" data-default-value="true" />
|
||||||
<label for="playerAutoplayAfterScreenshot">Autoplay after screenshots</label><br />
|
<label for="playerAutoplayAfterScreenshot">Autoplay after screenshots</label><br />
|
||||||
|
|
||||||
<input type="checkbox" id="playerAutopauseAfterFocusLost" data-default-value="true" />
|
|
||||||
<label for="playerAutopauseAfterFocusLost">Autopause after tab unfocused</label><br />
|
|
||||||
|
|
||||||
<input type="checkbox" id="playerAutoplayAfterFocusGain" data-default-value="true" />
|
|
||||||
<label for="playerAutoplayAfterFocusGain">Autoplay after tab focused</label><br />
|
|
||||||
|
|
||||||
<h3>Watch2gether</h3>
|
<h3>Watch2gether</h3>
|
||||||
<input type="checkbox" id="w2gDisplayCharacterCounter" data-default-value="true" />
|
<input type="checkbox" id="w2gDisplayCharacterCounter" data-default-value="true" />
|
||||||
<label for="w2gDisplayCharacterCounter">Display character count in chat</label><br />
|
<label for="w2gDisplayCharacterCounter">Display character count in chat</label><br />
|
||||||
<input type="checkbox" id="w2gAutoscrollToUnseen" data-default-value="true" />
|
|
||||||
<label for="w2gAutoscrollToUnseen">Autoscroll to the first unseen episode</label><br />
|
|
||||||
|
|
||||||
<input type="checkbox" id="w2gAutotoggleHide" data-default-value="true" />
|
|
||||||
<label for="w2gAutotoggleHide">Autotoggle the Hide-Button for w2g</label><br />
|
|
||||||
|
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<button id="btnSave">Save</button>
|
<button id="btnSave">Save</button>
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { init as languageDisplay } from './enhancements/languageDisplay';
|
||||||
import { init as notifications } from './enhancements/notifications';
|
import { init as notifications } from './enhancements/notifications';
|
||||||
import { init as quickSearch } from './enhancements/quickSearch';
|
import { init as quickSearch } from './enhancements/quickSearch';
|
||||||
import { init as timeConversion } from './enhancements/timeConversion';
|
import { init as timeConversion } from './enhancements/timeConversion';
|
||||||
import { init as watch2gether } from './enhancements/watch2gether';
|
import { init as watch2getherChat } from './enhancements/watch2getherChat';
|
||||||
// css
|
// css
|
||||||
import { init as cssEnhancements } from './enhancements/cssEnhancements';
|
import { init as cssEnhancements } from './enhancements/cssEnhancements';
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ languageDisplay();
|
||||||
notifications();
|
notifications();
|
||||||
quickSearch();
|
quickSearch();
|
||||||
timeConversion();
|
timeConversion();
|
||||||
watch2gether();
|
watch2getherChat();
|
||||||
|
|
||||||
// css
|
// css
|
||||||
cssEnhancements();
|
cssEnhancements();
|
|
@ -14,13 +14,8 @@ export const SETTINGS_animeLanguageDisplay = 'animeLanguageDisplay';
|
||||||
export const SETTINGS_requestBeautifyPage = 'requestBeautifyPage';
|
export const SETTINGS_requestBeautifyPage = 'requestBeautifyPage';
|
||||||
// player
|
// player
|
||||||
export const SETTINGS_playerAutoplayAfterScreenshot = 'playerAutoplayAfterScreenshot';
|
export const SETTINGS_playerAutoplayAfterScreenshot = 'playerAutoplayAfterScreenshot';
|
||||||
export const SETTINGS_playerAutopauseAfterFocusLost = 'playerAutopauseAfterFocusLost';
|
|
||||||
export const SETTINGS_playerAutoplayAfterFocusGain = 'playerAutoplayAfterFocusGain';
|
|
||||||
// w2g
|
// w2g
|
||||||
export const SETTINGS_w2gDisplayCharacterCounter = 'w2gDisplayCharacterCounter';
|
export const SETTINGS_w2gDisplayCharacterCounter = 'w2gDisplayCharacterCounter';
|
||||||
export const SETTINGS_w2gAutotoggleHide = 'w2gAutotoggleHide';
|
|
||||||
export const SETTINGS_w2gAutoscrollToUnseen = 'w2gAutoscrollToUnseen';
|
|
||||||
|
|
||||||
class Configuration {
|
class Configuration {
|
||||||
settingsCache: Map<string, boolean>;
|
settingsCache: Map<string, boolean>;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import { getGlobalConfiguration,
|
import { getGlobalConfiguration, SETTINGS_playerAutoplayAfterScreenshot } from '../configuration/configuration';
|
||||||
SETTINGS_playerAutoplayAfterScreenshot,
|
|
||||||
SETTINGS_playerAutopauseAfterFocusLost,
|
|
||||||
SETTINGS_playerAutoplayAfterFocusGain } from '../configuration/configuration';
|
|
||||||
import * as core from '../utils/aniwatchCore';
|
import * as core from '../utils/aniwatchCore';
|
||||||
import * as helper from '../utils/helpers';
|
import * as helper from '../utils/helpers';
|
||||||
|
|
||||||
const SCREENSHOT_TOOLTIP_ID = 'anilyr-screenshots-tooltip';
|
const SCREENSHOT_TOOLTIP_ID = 'anilyr-screenshots-tooltip';
|
||||||
const PLAYER_ID = 'player';
|
const PLAYER_ID = 'player';
|
||||||
let resumePlayerOnVisible: boolean;
|
|
||||||
|
|
||||||
export function init(): void {
|
export function init(): void {
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_playerAutoplayAfterScreenshot, value => {
|
getGlobalConfiguration().getProperty(SETTINGS_playerAutoplayAfterScreenshot, value => {
|
||||||
|
@ -20,18 +16,6 @@ export function init(): void {
|
||||||
}, "^/anime/[0-9]*/[0-9]*$");
|
}, "^/anime/[0-9]*/[0-9]*$");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_playerAutopauseAfterFocusLost, value => {
|
|
||||||
if (value) {
|
|
||||||
core.registerScript((node: Node) => {
|
|
||||||
window.addEventListener('visibilitychange', observeTabFocus, false);
|
|
||||||
}, "^/anime/[0-9]*/[0-9]*$");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_playerAutoplayAfterFocusGain, value => {
|
|
||||||
resumePlayerOnVisible = value;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function observeScreenshotTooltip(tooltip: HTMLElement): void {
|
function observeScreenshotTooltip(tooltip: HTMLElement): void {
|
||||||
|
@ -39,7 +23,7 @@ function observeScreenshotTooltip(tooltip: HTMLElement): void {
|
||||||
mutations.forEach(mutation => {
|
mutations.forEach(mutation => {
|
||||||
// Switched to invisible
|
// Switched to invisible
|
||||||
if (!mutation.oldValue.includes('display: none') && helper.isHtmlElement(mutation.target) && (mutation.target as HTMLElement).style.display == 'none') {
|
if (!mutation.oldValue.includes('display: none') && helper.isHtmlElement(mutation.target) && (mutation.target as HTMLElement).style.display == 'none') {
|
||||||
let playerElement = findPlayerElement(PLAYER_ID);
|
let playerElement = findPlayerElement();
|
||||||
if (helper.assigned(playerElement)) {
|
if (helper.assigned(playerElement)) {
|
||||||
resumePlayer(playerElement);
|
resumePlayer(playerElement);
|
||||||
}
|
}
|
||||||
|
@ -54,24 +38,8 @@ function observeScreenshotTooltip(tooltip: HTMLElement): void {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findPlayerElement(): HTMLVideoElement {
|
||||||
function observeTabFocus(): void {
|
let playerCandidate = document.getElementById(PLAYER_ID);
|
||||||
let docState = document.visibilityState;
|
|
||||||
let playerElement = findPlayerElement(PLAYER_ID);
|
|
||||||
if (docState === 'hidden') {
|
|
||||||
if (helper.assigned(playerElement)) {
|
|
||||||
pausePlayer(playerElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (docState === 'visible' && resumePlayerOnVisible) {
|
|
||||||
if (helper.assigned(playerElement)) {
|
|
||||||
resumePlayer(playerElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findPlayerElement(id: string): HTMLVideoElement {
|
|
||||||
let playerCandidate = document.getElementById(id);
|
|
||||||
if (playerCandidate instanceof HTMLVideoElement) {
|
if (playerCandidate instanceof HTMLVideoElement) {
|
||||||
return playerCandidate;
|
return playerCandidate;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +50,3 @@ export function findPlayerElement(id: string): HTMLVideoElement {
|
||||||
function resumePlayer(player: HTMLVideoElement) {
|
function resumePlayer(player: HTMLVideoElement) {
|
||||||
player.play();
|
player.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
function pausePlayer(player: HTMLVideoElement) {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
|
@ -1,153 +0,0 @@
|
||||||
import * as core from '../utils/aniwatchCore';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
import { getGlobalConfiguration, SETTINGS_w2gDisplayCharacterCounter, SETTINGS_w2gAutotoggleHide, SETTINGS_w2gAutoscrollToUnseen } from '../configuration/configuration';
|
|
||||||
import { assigned } from '../utils/helpers';
|
|
||||||
import { findPlayerElement } from "../enhancements/anilyr";
|
|
||||||
|
|
||||||
const PLAYER_ID = 'wPlayer';
|
|
||||||
let hidden: boolean;
|
|
||||||
|
|
||||||
export function init(): void {
|
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_w2gDisplayCharacterCounter, value => {
|
|
||||||
if (value) {
|
|
||||||
core.runAfterLoad(() => {
|
|
||||||
manipulateChatInput();
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
|
|
||||||
core.runAfterLocationChange(() => {
|
|
||||||
manipulateChatInput();
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_w2gAutotoggleHide, value => {
|
|
||||||
if (value) {
|
|
||||||
core.runAfterLoad(() => {
|
|
||||||
addAutohideListener();
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
|
|
||||||
core.runAfterLocationChange(() => {
|
|
||||||
addAutohideListener();
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getGlobalConfiguration().getProperty(SETTINGS_w2gAutoscrollToUnseen, value => {
|
|
||||||
if (value) {
|
|
||||||
core.runAfterLoad(() => {
|
|
||||||
let element = findSearchResults();
|
|
||||||
if (assigned(element)) {
|
|
||||||
scrollSearchResults(element);
|
|
||||||
}
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
|
|
||||||
core.runAfterLocationChange(() => {
|
|
||||||
let element = findSearchResults();
|
|
||||||
if (assigned(element)) {
|
|
||||||
scrollSearchResults(element);
|
|
||||||
}
|
|
||||||
}, "^/watch2gether/.*$");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function manipulateChatInput(): void {
|
|
||||||
let textarea = document.querySelector('.chat-input textarea') as HTMLTextAreaElement;
|
|
||||||
|
|
||||||
// avoid duplicate registration
|
|
||||||
if (assigned(textarea.dataset.charCounterId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addCharCounter(textarea);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCharCounter(textarea: HTMLTextAreaElement): void {
|
|
||||||
let chatDiv = textarea.parentElement.parentElement; // div with chat input and controls
|
|
||||||
let controlRow = chatDiv.children[1]; // row with controls
|
|
||||||
let btn = controlRow.querySelector('button'); // find send button
|
|
||||||
|
|
||||||
let charCounterSpan = document.createElement('span'); // create span for counter
|
|
||||||
charCounterSpan.classList.add('awp-w2g-chatCounter');
|
|
||||||
|
|
||||||
// id and "connection"
|
|
||||||
let counterId = `awp-${uuidv4()}`
|
|
||||||
charCounterSpan.id = counterId;
|
|
||||||
textarea.dataset.charCounterId = counterId;
|
|
||||||
|
|
||||||
btn.parentElement.insertBefore(charCounterSpan, btn); // and insert in front of the button
|
|
||||||
updateCharCounter(textarea, charCounterSpan);
|
|
||||||
|
|
||||||
textarea.addEventListener('keyup', () => {
|
|
||||||
updateCharCounter(textarea, charCounterSpan)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCharCounter(textarea: HTMLTextAreaElement, charCounterSpan: HTMLSpanElement): void {
|
|
||||||
const SHAKE_CLASS = 'awp-w2g-chatCounter-max';
|
|
||||||
|
|
||||||
let current = textarea.value.length;
|
|
||||||
let max = textarea.maxLength;
|
|
||||||
|
|
||||||
charCounterSpan.innerText = `${current} / ${max}`;
|
|
||||||
|
|
||||||
// animation if at max
|
|
||||||
if (current >= max && !charCounterSpan.classList.contains(SHAKE_CLASS)) {
|
|
||||||
charCounterSpan.classList.add(SHAKE_CLASS);
|
|
||||||
|
|
||||||
// remove css class after animation finished, so it can be restarted again
|
|
||||||
setTimeout(() => {
|
|
||||||
charCounterSpan.classList.remove(SHAKE_CLASS);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addAutohideListener(): void {
|
|
||||||
let playerElement = findPlayerElement(PLAYER_ID);
|
|
||||||
let hideButton: HTMLButtonElement = document.getElementsByClassName('no-margin md-button md-ink-ripple layout-align-center-center layout-row')[0] as HTMLButtonElement;
|
|
||||||
if (assigned(playerElement) && assigned(hideButton)) {
|
|
||||||
if (hideButton.textContent.includes('HIDE')) {
|
|
||||||
hidden = false;
|
|
||||||
} else if (hideButton.textContent.includes('SHOW')) {
|
|
||||||
hidden = true;
|
|
||||||
}
|
|
||||||
playerElement.addEventListener('play', fn => {
|
|
||||||
if (!hidden) {
|
|
||||||
hideButton.click();
|
|
||||||
hidden = !hidden;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
playerElement.addEventListener('pause', fn => {
|
|
||||||
if (hidden) {
|
|
||||||
hideButton.click();
|
|
||||||
hidden = !hidden;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function scrollSearchResults(searchRes: Element): void {
|
|
||||||
let observer = new MutationObserver(mutations => {
|
|
||||||
let scrollTarget = searchRes.querySelector('md-list-item:not(.animelist-completed):not(.animelist-completed-add)') as HTMLElement;
|
|
||||||
|
|
||||||
if (assigned(scrollTarget)) {
|
|
||||||
// The node isn´t in its correct position directly when it´s added so we wait a small bit of time before we start scrolling.
|
|
||||||
// Also works for long loading lists which need more time to load than we wait (for example One Piece).
|
|
||||||
window.setTimeout(() => {
|
|
||||||
// scroll container to episode first
|
|
||||||
searchRes.scrollTop = scrollTarget.offsetTop;
|
|
||||||
|
|
||||||
// then scroll page to episode if neccessarry
|
|
||||||
scrollTarget.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(searchRes, {
|
|
||||||
childList: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function findSearchResults(): Element {
|
|
||||||
return document.querySelector('.search-results .ep-view');
|
|
||||||
}
|
|
65
src/javascript/enhancements/watch2getherChat.ts
Normal file
65
src/javascript/enhancements/watch2getherChat.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as core from '../utils/aniwatchCore';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { getGlobalConfiguration, SETTINGS_w2gDisplayCharacterCounter } from '../configuration/configuration';
|
||||||
|
import { assigned } from '../utils/helpers';
|
||||||
|
|
||||||
|
export function init(): void {
|
||||||
|
getGlobalConfiguration().getProperty(SETTINGS_w2gDisplayCharacterCounter, value => {
|
||||||
|
if (value) {
|
||||||
|
core.runAfterLocationChange(() => {
|
||||||
|
manipulateChatInput();
|
||||||
|
}, "^/watch2gether/.*$");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function manipulateChatInput(): void {
|
||||||
|
let textarea = document.querySelector('.chat-input textarea') as HTMLTextAreaElement;
|
||||||
|
|
||||||
|
// avoid duplicate registration
|
||||||
|
if (assigned(textarea.dataset.charCounterId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addCharCounter(textarea);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCharCounter(textarea: HTMLTextAreaElement): void {
|
||||||
|
let chatDiv = textarea.parentElement.parentElement; // div with chat input and controls
|
||||||
|
let controlRow = chatDiv.children[1]; // row with controls
|
||||||
|
let btn = controlRow.querySelector('button'); // find send button
|
||||||
|
|
||||||
|
let charCounterSpan = document.createElement('span'); // create span for counter
|
||||||
|
charCounterSpan.classList.add('awp-w2g-chatCounter');
|
||||||
|
|
||||||
|
// id and "connection"
|
||||||
|
let counterId = `awp-${uuidv4()}`
|
||||||
|
charCounterSpan.id = counterId;
|
||||||
|
textarea.dataset.charCounterId = counterId;
|
||||||
|
|
||||||
|
btn.parentElement.insertBefore(charCounterSpan, btn); // and insert in front of the button
|
||||||
|
updateCharCounter(textarea, charCounterSpan);
|
||||||
|
|
||||||
|
textarea.addEventListener('keyup', () => {
|
||||||
|
updateCharCounter(textarea, charCounterSpan)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCharCounter(textarea: HTMLTextAreaElement, charCounterSpan: HTMLSpanElement): void {
|
||||||
|
const SHAKE_CLASS = 'awp-w2g-chatCounter-max';
|
||||||
|
|
||||||
|
let current = textarea.value.length;
|
||||||
|
let max = textarea.maxLength;
|
||||||
|
|
||||||
|
charCounterSpan.innerText = `${current} / ${max}`;
|
||||||
|
|
||||||
|
// animation if at max
|
||||||
|
if (current >= max && !charCounterSpan.classList.contains(SHAKE_CLASS)) {
|
||||||
|
charCounterSpan.classList.add(SHAKE_CLASS);
|
||||||
|
|
||||||
|
// remove css class after animation finished, so it can be restarted again
|
||||||
|
setTimeout(() => {
|
||||||
|
charCounterSpan.classList.remove(SHAKE_CLASS);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ export function findTextNodes(baseNode: Node): Array<Node> {
|
||||||
baseNode = document.documentElement;
|
baseNode = document.documentElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
let walker = document.createTreeWalker(baseNode, NodeFilter.SHOW_TEXT, null);
|
let walker = document.createTreeWalker(baseNode, NodeFilter.SHOW_TEXT, null, false);
|
||||||
let node;
|
let node;
|
||||||
let results = [];
|
let results = [];
|
||||||
while (node = walker.nextNode()) {
|
while (node = walker.nextNode()) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Aniwatch Plus",
|
"name": "Aniwatch Plus",
|
||||||
"short_name": "AW+",
|
"short_name": "AW+",
|
||||||
"version": "1.1.0.0",
|
"version": "1.0.0.0",
|
||||||
"version_name": "1.1",
|
"version_name": "1.0",
|
||||||
"description": "Aniwatch Plus is an unofficial extension which provides several UI improvements for https://aniwatch.me.",
|
"description": "Aniwatch Plus is an unofficial extension which provides several UI improvements for https://aniwatch.me.",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
|
|
Loading…
Reference in a new issue