chore: update workflow

This commit is contained in:
DIYgod 2019-09-25 19:08:57 +08:00
parent 6f4cece562
commit 8ff2095ff6
No known key found for this signature in database
GPG Key ID: EC0B76A252D3EF67
24 changed files with 6730 additions and 3861 deletions

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
dist
demo
docs

View File

@ -1,15 +1,16 @@
{
"extends": "eslint:recommended",
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
"plugins": ["prettier"],
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 2018,
"sourceType": "module"
},
"env": {
"browser": true
"es6": true,
"browser": true,
"node": true,
},
"rules": {
"no-console": 0,
"no-extra-parens": 1,
"block-scoped-var": 1,
"curly": 1,
"eqeqeq": 1,
@ -20,10 +21,8 @@
"comma-spacing": 1,
"comma-style": 1,
"func-call-spacing": 1,
"indent": 1,
"keyword-spacing": 1,
"linebreak-style": 1,
"lines-around-comment": 1,
"no-multiple-empty-lines": 1,
"space-infix-ops": 1,
"arrow-spacing": 1,
@ -31,14 +30,12 @@
"prefer-const": 1,
"no-unsafe-negation": 1,
"array-callback-return": 1,
"dot-location": 1,
"dot-notation": 1,
"no-eval": 1,
"no-extend-native": 1,
"no-extra-label": 1,
"semi": 1,
"space-before-blocks": 1,
"space-before-function-paren": 1,
"space-in-parens": 1,
"space-unary-ops": 1,
"spaced-comment": 1,
@ -50,13 +47,10 @@
"no-useless-rename": 1,
"rest-spread-spacing": 1,
"no-trailing-spaces": 1,
"quotes": [1, "single"]
},
"globals": {
"require": false,
"module": false,
"Hls": false,
"flvjs": false,
"dashjs": false
"no-control-regex": 0,
"prettier/prettier": 0,
"no-await-in-loop": 1,
"require-atomic-updates": 0,
"no-prototype-builtins": 0
}
}
}

View File

@ -2,6 +2,6 @@
If you want to report a bug, please provide the following information:
- The steps to reproduce.
- A minimal demo of the problem via https://jsfiddle.net or http://codepen.io/pen if possible.
- Which versions of APlayer, and which browser / OS are affected by this issue?
- The steps to reproduce.
- A minimal demo of the problem via https://jsfiddle.net or http://codepen.io/pen if possible.
- Which versions of APlayer, and which browser / OS are affected by this issue?

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
dist
demo
docs

7
.prettierrc Normal file
View File

@ -0,0 +1,7 @@
{
"printWidth": 233,
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "es5",
"arrowParens": "always"
}

View File

@ -1,7 +1,10 @@
language: node_js
node_js:
- "node"
- lts/*
script:
- npm run build
cache:
yarn: true

View File

@ -21,13 +21,8 @@ APlayer is a lovely HTML5 music player.
**APlayer supports:**
- Media formats
- MP4 H.264 (AAC or MP3)
- WAVE PCM
- Ogg Theora Vorbis
- Features
- Playlist
- Lyrics
- Media formats - MP4 H.264 (AAC or MP3) - WAVE PCM - Ogg Theora Vorbis
- Features - Playlist - Lyrics
Using APlayer on your project? [Let me know!](https://github.com/MoePlayer/APlayer/issues/79)
@ -37,44 +32,44 @@ Using APlayer on your project? [Let me know!](https://github.com/MoePlayer/APlay
## Join the Discussion
- [Telegram Group](https://t.me/adplayer)
- [QQ Group](https://shang.qq.com/wpa/qunwpa?idkey=bf22213ae0028a82e5adf3f286dfd4f01e0997dc9f1dcd8e831a0a85e799be17): 415835947
- [Telegram Group](https://t.me/adplayer)
- [QQ Group](https://shang.qq.com/wpa/qunwpa?idkey=bf22213ae0028a82e5adf3f286dfd4f01e0997dc9f1dcd8e831a0a85e799be17): 415835947
## Related Projects
### Plugins
- [APlayer-Typecho-Plugin](https://github.com/zgq354/APlayer-Typecho-Plugin): Typecho
- [hexo-tag-aplayer](https://github.com/grzhan/hexo-tag-aplayer): Hexo
- [Hermit-X(APlayer for WordPress)](https://github.com/liwanglin12/Hermit-X): WordPress
- [APlayerHandle](https://github.com/kn007/APlayerHandle): WordPress
- [APlayer_for_Z-BlogPHP](https://github.com/fghrsh/APlayer_for_Z-BlogPHP): Z-BlogPHP
- [react-aplayer](https://github.com/sabrinaluo/react-aplayer): React
- [Vue-APlayer](https://github.com/SevenOutman/vue-aplayer): Vue
- [vue-aplayer](https://github.com/MoeFE/vue-aplayer): Vue
- [php-aplayer](https://github.com/Daryl-L/php-aplayer): PHP
- [APlayer-Typecho-Plugin](https://github.com/zgq354/APlayer-Typecho-Plugin): Typecho
- [hexo-tag-aplayer](https://github.com/grzhan/hexo-tag-aplayer): Hexo
- [Hermit-X(APlayer for WordPress)](https://github.com/liwanglin12/Hermit-X): WordPress
- [APlayerHandle](https://github.com/kn007/APlayerHandle): WordPress
- [APlayer_for_Z-BlogPHP](https://github.com/fghrsh/APlayer_for_Z-BlogPHP): Z-BlogPHP
- [react-aplayer](https://github.com/sabrinaluo/react-aplayer): React
- [Vue-APlayer](https://github.com/SevenOutman/vue-aplayer): Vue
- [vue-aplayer](https://github.com/MoeFE/vue-aplayer): Vue
- [php-aplayer](https://github.com/Daryl-L/php-aplayer): PHP
### Tooling
- [APlayer-Controler](https://github.com/Mashiro-Sorata/APlayer-Controler): controling tool
- [MetingJS](https://github.com/metowolf/MetingJS): work with Meting music API
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/APlayer/issues/79)
- [APlayer-Controler](https://github.com/Mashiro-Sorata/APlayer-Controler): controling tool
- [MetingJS](https://github.com/metowolf/MetingJS): work with Meting music API
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/APlayer/issues/79)
## Who use APlayer?
- [bilibili](https://www.bilibili.com/): 国内知名的视频弹幕网站
- [黑客派](https://hacpai.com/): 程序员和设计师的聚集地,一个活跃的小众社区
- [浙江大学CC98论坛](https://zh.wikipedia.org/wiki/CC98%E8%AE%BA%E5%9D%9B): 浙江大学校网内规模最大的论坛中国各大学中较活跃的BBS之一
- [Jelly Rue](http://jellyrue.com/): Jelly Rue, an indie pop-rock band from Tartu.
- [Opus](http://www.opusopus.co/): An artist-exploration data visualization application
- [站长之家](http://www.chinaz.com/15year/index.html): 针对中文站点提供资讯、技术、资源、服务
- [LLSupport](https://www.lovelivesupport.com/): This site provides a lot of information about LoveLive
- [歌词千寻](https://www.lrcgc.com/diy): 每日更新的LRC歌词网站
- [iSearch](http://i.oppsu.cn): 一个提供 iTunes 搜索,试听,高清专辑封面获取,查看最新音乐动态等综合性平台
- [LRC歌词编辑器](https://github.com/MoeFE/Lyric): 一款非常实用的在线LRC歌词编辑器
- [Аэростатика](https://aerostatica.ru/)
- [HealthDig](https://healthdig.co): 每天只需两分钟的重点新闻资讯
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/APlayer/issues/79)
- [bilibili](https://www.bilibili.com/): 国内知名的视频弹幕网站
- [黑客派](https://hacpai.com/): 程序员和设计师的聚集地,一个活跃的小众社区
- [浙江大学 CC98 论坛](https://zh.wikipedia.org/wiki/CC98%E8%AE%BA%E5%9D%9B): 浙江大学校网内规模最大的论坛,中国各大学中较活跃的 BBS 之一
- [Jelly Rue](http://jellyrue.com/): Jelly Rue, an indie pop-rock band from Tartu.
- [Opus](http://www.opusopus.co/): An artist-exploration data visualization application
- [站长之家](http://www.chinaz.com/15year/index.html): 针对中文站点提供资讯、技术、资源、服务
- [LLSupport](https://www.lovelivesupport.com/): This site provides a lot of information about LoveLive
- [歌词千寻](https://www.lrcgc.com/diy): 每日更新的 LRC 歌词网站
- [iSearch](http://i.oppsu.cn): 一个提供 iTunes 搜索,试听,高清专辑封面获取,查看最新音乐动态等综合性平台
- [LRC 歌词编辑器](https://github.com/MoeFE/Lyric): 一款非常实用的在线 LRC 歌词编辑器
- [Аэростатика](https://aerostatica.ru/)
- [HealthDig](https://healthdig.co): 每天只需两分钟的重点新闻资讯
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/APlayer/issues/79)
## Current Premium Sponsors
@ -105,17 +100,17 @@ APlayer is an MIT licensed open source project and completely free to use. Howev
We accept donations through these channels:
- [Paypal](https://www.paypal.me/DIYgod)
- [WeChat Pay](https://i.imgur.com/aq6PtWa.png)
- [Alipay](https://i.imgur.com/wv1Pj2k.png)
- Bitcoin: 13CwQLHzPYm2tewNMSJBeArbbRM5NSmCD1
- [Paypal](https://www.paypal.me/DIYgod)
- [WeChat Pay](https://i.imgur.com/aq6PtWa.png)
- [Alipay](https://i.imgur.com/wv1Pj2k.png)
- Bitcoin: 13CwQLHzPYm2tewNMSJBeArbbRM5NSmCD1
## Recurring Pledges
Recurring pledges come with exclusive perks, e.g. having your name or your company logo listed in the APlayer GitHub repository and this website.
- Become a backer or sponsor via [OpenCollective](https://opencollective.com/aplayer)
- E-mail us: i#html.love
- Become a backer or sponsor via [OpenCollective](https://opencollective.com/aplayer)
- E-mail us: i#html.love
## Author

View File

@ -1,60 +1,80 @@
{
"name": "aplayer",
"version": "1.10.1",
"description": "Wow, such a beautiful html5 music player",
"main": "dist/APlayer.min.js",
"style": "dist/APlayer.min.css",
"scripts": {
"start": "npm run dev",
"build": "cross-env NODE_ENV=production webpack --config webpack/prod.config.js --progress --display-error-details --colors",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack/dev.config.js --watch --colors",
"test": "eslint src webpack"
},
"files": [
"dist"
],
"repository": {
"url": "git+https://github.com/DIYgod/APlayer.git",
"type": "git"
},
"keywords": [
"player",
"music",
"html5"
],
"author": "DIYgod",
"license": "MIT",
"bugs": {
"url": "https://github.com/DIYgod/APlayer/issues"
},
"homepage": "https://github.com/DIYgod/APlayer#readme",
"devDependencies": {
"art-template": "4.12.2",
"art-template-loader": "1.4.3",
"autoprefixer": "^8.6.2",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"cross-env": "^5.2.0",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"eslint-loader": "^2.0.0",
"git-revision-webpack-plugin": "^3.0.3",
"mini-css-extract-plugin": "0.4.0",
"node-sass": "^4.9.0",
"postcss-loader": "^2.1.5",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0",
"svg-inline-loader": "0.8.0",
"template-string-optimize-loader": "^2.2.3",
"url-loader": "^1.0.1",
"webpack": "^4.12.0",
"webpack-cli": "3.0.6",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"balloon-css": "^0.5.0",
"promise-polyfill": "8.0.0",
"smoothscroll": "0.4.0"
}
"name": "aplayer",
"version": "1.10.1",
"description": "Wow, such a beautiful html5 music player",
"main": "dist/APlayer.min.js",
"style": "dist/APlayer.min.css",
"scripts": {
"start": "npm run dev",
"build": "cross-env NODE_ENV=production webpack --config webpack/prod.config.js --progress --display-error-details --colors",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack/dev.config.js --watch --colors",
"test": "eslint src webpack",
"format": "eslint \"**/*.js\" --fix && prettier \"**/*.{js,json,md}\" --write",
"format:staged": "eslint \"**/*.js\" --fix && pretty-quick --staged --verbose --pattern \"**/*.{js,json,md}\"",
"format:check": "eslint \"**/*.js\" && prettier-check \"**/*.{js,json,md}\""
},
"files": [
"dist"
],
"repository": {
"url": "git+https://github.com/DIYgod/APlayer.git",
"type": "git"
},
"keywords": [
"player",
"music",
"html5"
],
"gitHooks": {
"pre-commit": "npm run format:staged"
},
"author": "DIYgod",
"license": "MIT",
"bugs": {
"url": "https://github.com/DIYgod/APlayer/issues"
},
"homepage": "https://github.com/DIYgod/APlayer#readme",
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/preset-env": "^7.4.5",
"@vuepress/plugin-back-to-top": "1.1.0",
"@vuepress/plugin-google-analytics": "1.1.0",
"@vuepress/plugin-pwa": "1.1.0",
"art-template": "4.13.2",
"art-template-loader": "1.4.3",
"autoprefixer": "^9.6.1",
"babel-loader": "^8.0.6",
"cross-env": "^6.0.0",
"css-loader": "^3.2.0",
"cssnano": "^4.1.10",
"eslint": "^6.4.0",
"eslint-config-prettier": "^6.3.0",
"eslint-loader": "^3.0.0",
"eslint-plugin-prettier": "^3.1.1",
"exports-loader": "^0.7.0",
"file-loader": "^4.0.0",
"git-revision-webpack-plugin": "^3.0.3",
"mini-css-extract-plugin": "0.8.0",
"node-sass": "^4.12.0",
"postcss-loader": "^3.0.0",
"prettier": "^1.18.2",
"prettier-check": "^2.0.0",
"pretty-quick": "^1.11.1",
"sass-loader": "^8.0.0",
"strip-loader": "^0.1.2",
"style-loader": "^1.0.0",
"svg-inline-loader": "0.8.0",
"template-string-optimize-loader": "^3.0.0",
"url-loader": "^2.1.0",
"vuepress": "1.1.0",
"webpack": "^4.40.2",
"webpack-cli": "3.3.9",
"webpack-dev-server": "^3.8.1",
"yorkie": "^2.0.0"
},
"dependencies": {
"balloon-css": "^1.0.3",
"promise-polyfill": "8.1.3",
"smoothscroll": "0.4.0"
}
}

View File

@ -1,5 +1,5 @@
class Bar {
constructor (template) {
constructor(template) {
this.elements = {};
this.elements.volume = template.volume;
this.elements.played = template.played;
@ -13,15 +13,15 @@ class Bar {
* @param {Number} percentage
* @param {String} direction - Point out the direction of this bar, Should be height or width
*/
set (type, percentage, direction) {
set(type, percentage, direction) {
percentage = Math.max(percentage, 0);
percentage = Math.min(percentage, 1);
this.elements[type].style[direction] = percentage * 100 + '%';
}
get (type, direction) {
get(type, direction) {
return parseFloat(this.elements[type].style[direction]) / 100;
}
}
export default Bar;
export default Bar;

View File

@ -2,7 +2,7 @@ import utils from './utils';
import Icons from './icons';
class Controller {
constructor (player) {
constructor(player) {
this.player = player;
this.initPlayButton();
@ -18,13 +18,13 @@ class Controller {
this.initLrcButton();
}
initPlayButton () {
initPlayButton() {
this.player.template.pic.addEventListener('click', () => {
this.player.toggle();
});
}
initPlayBar () {
initPlayBar() {
const thumbMove = (e) => {
let percentage = ((e.clientX || e.changedTouches[0].clientX) - this.player.template.barWrap.getBoundingClientRect().left) / this.player.template.barWrap.clientWidth;
percentage = Math.max(percentage, 0);
@ -52,12 +52,11 @@ class Controller {
});
}
initVolumeButton () {
initVolumeButton() {
this.player.template.volumeButton.addEventListener('click', () => {
if (this.player.audio.muted) {
this.player.volume(this.player.audio.volume, true);
}
else {
} else {
this.player.audio.muted = true;
this.player.switchVolumeIcon();
this.player.bar.set('volume', 0, 'height');
@ -88,41 +87,36 @@ class Controller {
});
}
initOrderButton () {
initOrderButton() {
this.player.template.order.addEventListener('click', () => {
if (this.player.options.order === 'list') {
this.player.options.order = 'random';
this.player.template.order.innerHTML = Icons.orderRandom;
}
else if (this.player.options.order === 'random') {
} else if (this.player.options.order === 'random') {
this.player.options.order = 'list';
this.player.template.order.innerHTML = Icons.orderList;
}
});
}
initLoopButton () {
initLoopButton() {
this.player.template.loop.addEventListener('click', () => {
if (this.player.list.audios.length > 1) {
if (this.player.options.loop === 'one') {
this.player.options.loop = 'none';
this.player.template.loop.innerHTML = Icons.loopNone;
}
else if (this.player.options.loop === 'none') {
} else if (this.player.options.loop === 'none') {
this.player.options.loop = 'all';
this.player.template.loop.innerHTML = Icons.loopAll;
}
else if (this.player.options.loop === 'all') {
} else if (this.player.options.loop === 'all') {
this.player.options.loop = 'one';
this.player.template.loop.innerHTML = Icons.loopOne;
}
}
else {
} else {
if (this.player.options.loop === 'one' || this.player.options.loop === 'all') {
this.player.options.loop = 'none';
this.player.template.loop.innerHTML = Icons.loopNone;
}
else if (this.player.options.loop === 'none') {
} else if (this.player.options.loop === 'none') {
this.player.options.loop = 'all';
this.player.template.loop.innerHTML = Icons.loopAll;
}
@ -130,19 +124,19 @@ class Controller {
});
}
initMenuButton () {
initMenuButton() {
this.player.template.menu.addEventListener('click', () => {
this.player.list.toggle();
});
}
initMiniSwitcher () {
initMiniSwitcher() {
this.player.template.miniSwitcher.addEventListener('click', () => {
this.player.setMode(this.player.mode === 'mini' ? 'normal' : 'mini');
});
}
initSkipButton () {
initSkipButton() {
this.player.template.skipBackButton.addEventListener('click', () => {
this.player.skipBack();
});
@ -154,13 +148,12 @@ class Controller {
});
}
initLrcButton () {
initLrcButton() {
this.player.template.lrcButton.addEventListener('click', () => {
if (this.player.template.lrcButton.classList.contains('aplayer-icon-lrc-inactivity')) {
this.player.template.lrcButton.classList.remove('aplayer-icon-lrc-inactivity');
this.player.lrc && this.player.lrc.show();
}
else {
} else {
this.player.template.lrcButton.classList.add('aplayer-icon-lrc-inactivity');
this.player.lrc && this.player.lrc.hide();
}
@ -168,4 +161,4 @@ class Controller {
}
}
export default Controller;
export default Controller;

View File

@ -1,22 +1,36 @@
class Events {
constructor () {
constructor() {
this.events = {};
this.audioEvents = [
'abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error',
'loadeddata', 'loadedmetadata', 'loadstart', 'mozaudioavailable', 'pause', 'play',
'playing', 'progress', 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend',
'timeupdate', 'volumechange', 'waiting'
];
this.playerEvents = [
'destroy',
'listshow', 'listhide', 'listadd', 'listremove', 'listswitch', 'listclear',
'noticeshow', 'noticehide',
'lrcshow', 'lrchide',
'abort',
'canplay',
'canplaythrough',
'durationchange',
'emptied',
'ended',
'error',
'loadeddata',
'loadedmetadata',
'loadstart',
'mozaudioavailable',
'pause',
'play',
'playing',
'progress',
'ratechange',
'seeked',
'seeking',
'stalled',
'suspend',
'timeupdate',
'volumechange',
'waiting',
];
this.playerEvents = ['destroy', 'listshow', 'listhide', 'listadd', 'listremove', 'listswitch', 'listclear', 'noticeshow', 'noticehide', 'lrcshow', 'lrchide'];
}
on (name, callback) {
on(name, callback) {
if (this.type(name) && typeof callback === 'function') {
if (!this.events[name]) {
this.events[name] = [];
@ -25,7 +39,7 @@ class Events {
}
}
trigger (name, data) {
trigger(name, data) {
if (this.events[name] && this.events[name].length) {
for (let i = 0; i < this.events[name].length; i++) {
this.events[name][i](data);
@ -33,11 +47,10 @@ class Events {
}
}
type (name) {
type(name) {
if (this.playerEvents.indexOf(name) !== -1) {
return 'player';
}
else if (this.audioEvents.indexOf(name) !== -1) {
} else if (this.audioEvents.indexOf(name) !== -1) {
return 'audio';
}

View File

@ -4,4 +4,4 @@ import APlayer from './player';
/* global APLAYER_VERSION GIT_HASH */
console.log(`${'\n'} %c APlayer v${APLAYER_VERSION} ${GIT_HASH} %c http://aplayer.js.org ${'\n'}`, 'color: #fadfa3; background: #030307; padding:5px 0;', 'background: #fadfa3; padding:5px 0;');
export default APlayer;
export default APlayer;

View File

@ -3,7 +3,7 @@ import utils from './utils';
import smoothScroll from 'smoothscroll';
class List {
constructor (player) {
constructor(player) {
this.player = player;
this.index = 0;
this.audios = this.player.options.audio;
@ -13,34 +13,32 @@ class List {
this.bindEvents();
}
bindEvents () {
bindEvents() {
this.player.template.list.addEventListener('click', (e) => {
let target;
if (e.target.tagName.toUpperCase() === 'LI') {
target = e.target;
}
else {
} else {
target = e.target.parentElement;
}
const audioIndex = parseInt(target.getElementsByClassName('aplayer-list-index')[0].innerHTML) - 1;
if (audioIndex !== this.index) {
this.switch(audioIndex);
this.player.play();
}
else {
} else {
this.player.toggle();
}
});
}
show () {
show() {
this.showing = true;
this.player.template.list.scrollTop = this.index * 33;
this.player.template.list.style.height = `${Math.min(this.player.template.list.scrollHeight, this.player.options.listMaxHeight)}px`;
this.player.events.trigger('listshow');
}
hide () {
hide() {
this.showing = false;
this.player.template.list.style.height = `${Math.min(this.player.template.list.scrollHeight, this.player.options.listMaxHeight)}px`;
setTimeout(() => {
@ -49,16 +47,15 @@ class List {
}, 0);
}
toggle () {
toggle() {
if (this.showing) {
this.hide();
}
else {
} else {
this.show();
}
}
add (audios) {
add(audios) {
this.player.events.trigger('listadd', {
audios: audios,
});
@ -80,7 +77,7 @@ class List {
this.player.template.list.innerHTML += tplListItem({
theme: this.player.options.theme,
audio: audios,
index: this.audios.length + 1
index: this.audios.length + 1,
});
this.audios = this.audios.concat(audios);
@ -97,14 +94,13 @@ class List {
if (wasEmpty) {
if (this.player.options.order === 'random') {
this.switch(this.player.randomOrder[0]);
}
else {
} else {
this.switch(0);
}
}
}
remove (index) {
remove(index) {
this.player.events.trigger('listremove', {
index: index,
});
@ -119,8 +115,7 @@ class List {
if (index === this.index) {
if (this.audios[index]) {
this.switch(index);
}
else {
} else {
this.switch(index - 1);
}
}
@ -136,14 +131,13 @@ class List {
}
this.player.template.listCurs = this.player.container.querySelectorAll('.aplayer-list-cur');
}
else {
} else {
this.clear();
}
}
}
switch (index) {
switch(index) {
this.player.events.trigger('listswitch', {
index: index,
});
@ -173,13 +167,14 @@ class List {
this.player.lrc && this.player.lrc.update(0);
// set duration time
if (this.player.duration !== 1) { // compatibility: Android browsers will output 1 at first
if (this.player.duration !== 1) {
// compatibility: Android browsers will output 1 at first
this.player.template.dtime.innerHTML = utils.secondToTime(this.player.duration);
}
}
}
clear () {
clear() {
this.player.events.trigger('listclear');
this.index = 0;
this.player.container.classList.remove('aplayer-withlist');
@ -197,4 +192,4 @@ class List {
}
}
export default List;
export default List;

View File

@ -1,7 +1,7 @@
import tplLrc from '../template/lrc.art';
class Lrc {
constructor (options) {
constructor(options) {
this.container = options.container;
this.async = options.async;
this.player = options.player;
@ -10,26 +10,25 @@ class Lrc {
this.current = [];
}
show () {
show() {
this.player.events.trigger('lrcshow');
this.player.template.lrcWrap.classList.remove('aplayer-lrc-hide');
}
hide () {
hide() {
this.player.events.trigger('lrchide');
this.player.template.lrcWrap.classList.add('aplayer-lrc-hide');
}
toggle () {
toggle() {
if (this.player.template.lrcWrap.classList.contains('aplayer-lrc-hide')) {
this.show();
}
else {
} else {
this.hide();
}
}
update (currentTime = this.player.audio.currentTime) {
update(currentTime = this.player.audio.currentTime) {
if (this.index > this.current.length - 1 || currentTime < this.current[this.index][0] || (!this.current[this.index + 1] || currentTime >= this.current[this.index + 1][0])) {
for (let i = 0; i < this.current.length; i++) {
if (currentTime >= this.current[i][0] && (!this.current[i + 1] || currentTime < this.current[i + 1][0])) {
@ -43,30 +42,27 @@ class Lrc {
}
}
switch (index) {
switch(index) {
if (!this.parsed[index]) {
if (!this.async) {
if (this.player.list.audios[index].lrc) {
this.parsed[index] = this.parse(this.player.list.audios[index].lrc);
}
else {
} else {
this.parsed[index] = [['00:00', 'Not available']];
}
}
else {
} else {
this.parsed[index] = [['00:00', 'Loading']];
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (index === this.player.list.index && xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
this.parsed[index] = this.parse(xhr.responseText);
}
else {
} else {
this.player.notice(`LRC file request fails: status ${xhr.status}`);
this.parsed[index] = [['00:00', 'Not available']];
}
this.container.innerHTML = tplLrc({
lyrics: this.parsed[index]
lyrics: this.parsed[index],
});
this.update(0);
this.current = this.parsed[index];
@ -79,7 +75,7 @@ class Lrc {
}
this.container.innerHTML = tplLrc({
lyrics: this.parsed[index]
lyrics: this.parsed[index],
});
this.update(0);
this.current = this.parsed[index];
@ -97,7 +93,7 @@ class Lrc {
*
* @return {String} [[time, text], [time, text], [time, text], ...]
*/
parse (lrc_s) {
parse(lrc_s) {
if (lrc_s) {
lrc_s = lrc_s.replace(/([^\]^\n])\[/g, (match, p1) => p1 + '\n[');
const lyric = lrc_s.split('\n');
@ -107,7 +103,10 @@ class Lrc {
// match lrc time
const lrcTimes = lyric[i].match(/\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g);
// match lrc text
const lrcText = lyric[i].replace(/.*\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g, '').replace(/<(\d{2}):(\d{2})(\.(\d{2,3}))?>/g, '').replace(/^\s+|\s+$/g, '');
const lrcText = lyric[i]
.replace(/.*\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g, '')
.replace(/<(\d{2}):(\d{2})(\.(\d{2,3}))?>/g, '')
.replace(/^\s+|\s+$/g, '');
if (lrcTimes) {
// handle multiple time tag
@ -126,20 +125,19 @@ class Lrc {
lrc = lrc.filter((item) => item[1]);
lrc.sort((a, b) => a[0] - b[0]);
return lrc;
}
else {
} else {
return [];
}
}
remove (index) {
remove(index) {
this.parsed.splice(index, 1);
}
clear () {
clear() {
this.parsed = [];
this.container.innerHTML = '';
}
}
export default Lrc;
export default Lrc;

View File

@ -1,5 +1,4 @@
export default (options) => {
// default options
const defaultOption = {
container: options.element || document.getElementsByClassName('aplayer')[0],
@ -16,7 +15,7 @@ export default (options) => {
listFolded: options.fixed,
listMaxHeight: options.listmaxheight || 250,
audio: options.music || [],
storageName: 'aplayer-setting'
storageName: 'aplayer-setting',
};
for (const defaultKey in defaultOption) {
if (defaultOption.hasOwnProperty(defaultKey) && !options.hasOwnProperty(defaultKey)) {

View File

@ -15,14 +15,13 @@ import List from './list';
const instances = [];
class APlayer {
/**
* APlayer constructor function
*
* @param {Object} options - See README
* @constructor
*/
constructor (options) {
constructor(options) {
this.options = handleOption(options);
this.container = this.options.container;
this.paused = true;
@ -93,8 +92,7 @@ class APlayer {
this.bindEvents();
if (this.options.order === 'random') {
this.list.switch(this.randomOrder[0]);
}
else {
} else {
this.list.switch(0);
}
@ -106,7 +104,7 @@ class APlayer {
instances.push(this);
}
initAudio () {
initAudio() {
this.audio = document.createElement('audio');
this.audio.preload = this.options.preload;
@ -119,7 +117,7 @@ class APlayer {
this.volume(this.storage.get('volume'), true);
}
bindEvents () {
bindEvents() {
this.on('play', () => {
if (this.paused) {
this.setUIPlaying();
@ -145,7 +143,8 @@ class APlayer {
// show audio time: the metadata has loaded or changed
this.on('durationchange', () => {
if (this.duration !== 1) { // compatibility: Android browsers will output 1 at first
if (this.duration !== 1) {
// compatibility: Android browsers will output 1 at first
this.template.dtime.innerHTML = utils.secondToTime(this.duration);
}
});
@ -167,8 +166,7 @@ class APlayer {
this.play();
}
}, 2000);
}
else if (this.list.audios.length === 1) {
} else if (this.list.audios.length === 1) {
this.notice('An audio error has occurred.');
}
});
@ -183,35 +181,30 @@ class APlayer {
if (this.list.index < this.list.audios.length - 1) {
this.list.switch((this.list.index + 1) % this.list.audios.length);
this.play();
}
else {
} else {
this.list.switch((this.list.index + 1) % this.list.audios.length);
this.pause();
}
}
else if (this.options.order === 'random') {
} else if (this.options.order === 'random') {
if (this.randomOrder.indexOf(this.list.index) < this.randomOrder.length - 1) {
this.list.switch(this.nextIndex());
this.play();
}
else {
} else {
this.list.switch(this.nextIndex());
this.pause();
}
}
}
else if (this.options.loop === 'one') {
} else if (this.options.loop === 'one') {
this.list.switch(this.list.index);
this.play();
}
else if (this.options.loop === 'all') {
} else if (this.options.loop === 'all') {
this.skipForward();
this.play();
}
});
}
setAudio (audio) {
setAudio(audio) {
if (this.hls) {
this.hls.destroy();
this.hls = null;
@ -220,34 +213,28 @@ class APlayer {
if (this.options.customAudioType && this.options.customAudioType[type]) {
if (Object.prototype.toString.call(this.options.customAudioType[type]) === '[object Function]') {
this.options.customAudioType[type](this.audio, audio, this);
}
else {
} else {
console.error(`Illegal customType: ${type}`);
}
}
else {
} else {
if (!type || type === 'auto') {
if (/m3u8(#|\?|$)/i.exec(audio.url)) {
type = 'hls';
}
else {
} else {
type = 'normal';
}
}
if (type === 'hls') {
if (Hls.isSupported()) {
this.hls = new Hls();
if (window.Hls.isSupported()) {
this.hls = new window.Hls();
this.hls.loadSource(audio.url);
this.hls.attachMedia(this.audio);
}
else if (this.audio.canPlayType('application/x-mpegURL') || this.audio.canPlayType('application/vnd.apple.mpegURL')) {
} else if (this.audio.canPlayType('application/x-mpegURL') || this.audio.canPlayType('application/vnd.apple.mpegURL')) {
this.audio.src = audio.url;
}
else {
} else {
this.notice('Error: HLS is not supported.');
}
}
else if (type === 'normal') {
} else if (type === 'normal') {
this.audio.src = audio.url;
}
}
@ -258,7 +245,7 @@ class APlayer {
}
}
theme (color = this.list.audios[this.list.index].theme || this.options.theme, index = this.list.index, isReset = true) {
theme(color = this.list.audios[this.list.index].theme || this.options.theme, index = this.list.index, isReset = true) {
if (isReset) {
this.list.audios[index] && (this.list.audios[index].theme = color);
}
@ -271,7 +258,7 @@ class APlayer {
}
}
seek (time) {
seek(time) {
time = Math.max(time, 0);
time = Math.min(time, this.duration);
this.audio.currentTime = time;
@ -279,11 +266,11 @@ class APlayer {
this.template.ptime.innerHTML = utils.secondToTime(time);
}
get duration () {
get duration() {
return isNaN(this.audio.duration) ? 0 : this.audio.duration;
}
setUIPlaying () {
setUIPlaying() {
if (this.paused) {
this.paused = false;
this.template.button.classList.remove('aplayer-play');
@ -306,7 +293,7 @@ class APlayer {
}
}
play () {
play() {
this.setUIPlaying();
const playPromise = this.audio.play();
@ -320,7 +307,7 @@ class APlayer {
}
}
setUIPaused () {
setUIPaused() {
if (!this.paused) {
this.paused = true;
@ -337,19 +324,17 @@ class APlayer {
this.timer.disable('loading');
}
pause () {
pause() {
this.setUIPaused();
this.audio.pause();
}
switchVolumeIcon () {
switchVolumeIcon() {
if (this.volume() >= 0.95) {
this.template.volumeButton.innerHTML = Icons.volumeUp;
}
else if (this.volume() > 0) {
} else if (this.volume() > 0) {
this.template.volumeButton.innerHTML = Icons.volumeDown;
}
else {
} else {
this.template.volumeButton.innerHTML = Icons.volumeOff;
}
}
@ -357,7 +342,7 @@ class APlayer {
/**
* Set volume
*/
volume (percentage, nostorage) {
volume(percentage, nostorage) {
percentage = parseFloat(percentage);
if (!isNaN(percentage)) {
percentage = Math.max(percentage, 0);
@ -381,41 +366,40 @@ class APlayer {
/**
* bind events
*/
on (name, callback) {
on(name, callback) {
this.events.on(name, callback);
}
/**
* toggle between play and pause
*/
toggle () {
toggle() {
if (this.template.button.classList.contains('aplayer-play')) {
this.play();
}
else if (this.template.button.classList.contains('aplayer-pause')) {
} else if (this.template.button.classList.contains('aplayer-pause')) {
this.pause();
}
}
// abandoned
switchAudio (index) {
switchAudio(index) {
this.list.switch(index);
}
// abandoned
addAudio (audios) {
addAudio(audios) {
this.list.add(audios);
}
// abandoned
removeAudio (index) {
removeAudio(index) {
this.list.remove(index);
}
/**
* destroy this player
*/
destroy () {
destroy() {
instances.splice(instances.indexOf(this), 1);
this.pause();
this.container.innerHTML = '';
@ -424,17 +408,16 @@ class APlayer {
this.events.trigger('destroy');
}
setMode (mode = 'normal') {
setMode(mode = 'normal') {
this.mode = mode;
if (mode === 'mini') {
this.container.classList.add('aplayer-narrow');
}
else if (mode === 'normal') {
} else if (mode === 'normal') {
this.container.classList.remove('aplayer-narrow');
}
}
notice (text, time = 2000, opacity = 0.8) {
notice(text, time = 2000, opacity = 0.8) {
this.template.notice.innerHTML = text;
this.template.notice.style.opacity = opacity;
if (this.noticeTime) {
@ -451,55 +434,49 @@ class APlayer {
}
}
prevIndex () {
prevIndex() {
if (this.list.audios.length > 1) {
if (this.options.order === 'list') {
return this.list.index - 1 < 0 ? this.list.audios.length - 1 : this.list.index - 1;
}
else if (this.options.order === 'random') {
} else if (this.options.order === 'random') {
const index = this.randomOrder.indexOf(this.list.index);
if (index === 0) {
return this.randomOrder[this.randomOrder.length - 1];
}
else {
} else {
return this.randomOrder[index - 1];
}
}
}
else {
} else {
return 0;
}
}
nextIndex () {
nextIndex() {
if (this.list.audios.length > 1) {
if (this.options.order === 'list') {
return (this.list.index + 1) % this.list.audios.length;
}
else if (this.options.order === 'random') {
} else if (this.options.order === 'random') {
const index = this.randomOrder.indexOf(this.list.index);
if (index === this.randomOrder.length - 1) {
return this.randomOrder[0];
}
else {
} else {
return this.randomOrder[index + 1];
}
}
}
else {
} else {
return 0;
}
}
skipBack () {
skipBack() {
this.list.switch(this.prevIndex());
}
skipForward () {
skipForward() {
this.list.switch(this.nextIndex());
}
static get version () {
static get version() {
/* global APLAYER_VERSION */
return APLAYER_VERSION;
}

View File

@ -1,7 +1,7 @@
import utils from './utils';
class Storage {
constructor (player) {
constructor(player) {
this.storageName = player.options.storageName;
this.data = JSON.parse(utils.storage.get(this.storageName));
@ -11,14 +11,14 @@ class Storage {
this.data.volume = this.data.volume || player.options.volume;
}
get (key) {
get(key) {
return this.data[key];
}
set (key, value) {
set(key, value) {
this.data[key] = value;
utils.storage.set(this.storageName, JSON.stringify(this.data));
}
}
export default Storage;
export default Storage;

View File

@ -2,20 +2,19 @@ import Icons from './icons';
import tplPlayer from '../template/player.art';
class Template {
constructor (options) {
constructor(options) {
this.container = options.container;
this.options = options.options;
this.randomOrder = options.randomOrder;
this.init();
}
init () {
init() {
let cover = '';
if (this.options.audio.length) {
if (this.options.order === 'random') {
cover = this.options.audio[this.randomOrder[0]].cover;
}
else {
} else {
cover = this.options.audio[0].cover;
}
}

View File

@ -1,6 +1,5 @@
class Timer {
constructor (player) {
constructor(player) {
this.player = player;
window.requestAnimationFrame = (() =>
@ -9,23 +8,22 @@ class Timer {
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
function(callback) {
window.setTimeout(callback, 1000 / 60);
}
)();
})();
this.types = ['loading'];
this.init();
}
init () {
init() {
this.types.forEach((item) => {
this[`init${item}Checker`]();
});
}
initloadingChecker () {
initloadingChecker() {
let lastPlayPos = 0;
let currentPlayPos = 0;
let bufferingDetected = false;
@ -33,15 +31,11 @@ class Timer {
if (this.enableloadingChecker) {
// whether the audio is buffering
currentPlayPos = this.player.audio.currentTime;
if (!bufferingDetected
&& currentPlayPos === lastPlayPos
&& !this.player.audio.paused) {
if (!bufferingDetected && currentPlayPos === lastPlayPos && !this.player.audio.paused) {
this.player.container.classList.add('aplayer-loading');
bufferingDetected = true;
}
if (bufferingDetected
&& currentPlayPos > lastPlayPos
&& !this.player.audio.paused) {
if (bufferingDetected && currentPlayPos > lastPlayPos && !this.player.audio.paused) {
this.player.container.classList.remove('aplayer-loading');
bufferingDetected = false;
}
@ -50,7 +44,7 @@ class Timer {
}, 100);
}
enable (type) {
enable(type) {
this[`enable${type}Checker`] = true;
if (type === 'fps') {
@ -58,11 +52,11 @@ class Timer {
}
}
disable (type) {
disable(type) {
this[`enable${type}Checker`] = false;
}
destroy () {
destroy() {
this.types.forEach((item) => {
this[`enable${item}Checker`] = false;
this[`${item}Checker`] && clearInterval(this[`${item}Checker`]);
@ -70,4 +64,4 @@ class Timer {
}
}
export default Timer;
export default Timer;

View File

@ -1,15 +1,14 @@
const isMobile = /mobile/i.test(window.navigator.userAgent);
const utils = {
/**
* Parse second to time string
*
* @param {Number} second
* @return {String} 00:00 or 00:00:00
*/
* Parse second to time string
*
* @param {Number} second
* @return {String} 00:00 or 00:00:00
*/
secondToTime: (second) => {
const add0 = (num) => num < 10 ? '0' + num : '' + num;
const add0 = (num) => (num < 10 ? '0' + num : '' + num);
const hour = Math.floor(second / 3600);
const min = Math.floor((second - hour * 3600) / 60);
const sec = Math.floor(second - hour * 3600 - min * 60);
@ -23,20 +22,20 @@ const utils = {
localStorage.setItem(key, value);
},
get: (key) => localStorage.getItem(key)
get: (key) => localStorage.getItem(key),
},
nameMap: {
dragStart: isMobile ? 'touchstart' : 'mousedown',
dragMove: isMobile ? 'touchmove' : 'mousemove',
dragEnd: isMobile ? 'touchend' : 'mouseup'
dragEnd: isMobile ? 'touchend' : 'mouseup',
},
/**
* get random order, using FisherYates shuffle
*/
randomOrder: (length) => {
function shuffle (arr) {
function shuffle(arr) {
for (let i = arr.length - 1; i >= 0; i--) {
const randomIndex = Math.floor(Math.random() * (i + 1));
const itemAtIndex = arr[randomIndex];
@ -45,10 +44,12 @@ const utils = {
}
return arr;
}
return shuffle([...Array(length)].map(function (item, i) {
return i;
}));
}
return shuffle(
[...Array(length)].map(function(item, i) {
return i;
})
);
},
};
export default utils;
export default utils;

View File

@ -1,17 +1,17 @@
/* eslint-disable no-undef */
const path = require('path');
const webpack = require('webpack');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
mode: 'development',
devtool: 'cheap-module-source-map',
entry: {
'APlayer': './src/js/index.js'
APlayer: './src/js/index.js',
},
output: {
@ -21,23 +21,17 @@ module.exports = {
libraryTarget: 'umd',
libraryExport: 'default',
umdNamedDefine: true,
publicPath: '/'
publicPath: '/',
},
resolve: {
modules: ['node_modules'],
extensions: ['.js', '.scss']
extensions: ['.js', '.scss'],
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.js$/,
enforce: 'pre',
loader: 'eslint-loader',
include: path.resolve(__dirname, '../src/js'),
},
{
test: /\.js$/,
use: [
@ -45,10 +39,10 @@ module.exports = {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['env']
}
}
]
presets: ['@babel/preset-env'],
},
},
],
},
{
test: /\.scss$/,
@ -57,36 +51,34 @@ module.exports = {
{
loader: 'css-loader',
options: {
importLoaders: 1
}
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
options: {
config: {
path: path.join(__dirname, 'postcss.config.js')
}
}
plugins: [autoprefixer, cssnano],
},
},
'sass-loader'
]
'sass-loader',
],
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
options: {
'limit': 40000
}
limit: 40000,
},
},
{
test: /\.svg$/,
loader: 'svg-inline-loader'
loader: 'svg-inline-loader',
},
{
test: /\.art$/,
loader: 'art-template-loader'
}
]
loader: 'art-template-loader',
},
],
},
devServer: {
@ -96,29 +88,28 @@ module.exports = {
quiet: false,
open: true,
historyApiFallback: {
disableDotRule: true
disableDotRule: true,
},
watchOptions: {
ignored: /node_modules/
}
ignored: /node_modules/,
},
},
plugins: [
new webpack.DefinePlugin({
APLAYER_VERSION: `"${require('../package.json').version}"`,
GIT_HASH: JSON.stringify(gitRevisionPlugin.version())
})
GIT_HASH: JSON.stringify(gitRevisionPlugin.version()),
}),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty'
tls: 'empty',
},
performance: {
hints: false
}
hints: false,
},
};

View File

@ -1,5 +0,0 @@
module.exports = {
plugins: {
'autoprefixer': {}
}
};

View File

@ -1,12 +1,11 @@
/* eslint-disable no-undef */
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
mode: 'production',
bail: true,
@ -14,7 +13,7 @@ module.exports = {
devtool: 'source-map',
entry: {
'APlayer': './src/js/index.js'
APlayer: './src/js/index.js',
},
output: {
@ -24,23 +23,17 @@ module.exports = {
libraryTarget: 'umd',
libraryExport: 'default',
umdNamedDefine: true,
publicPath: '/'
publicPath: '/',
},
resolve: {
modules: ['node_modules'],
extensions: ['.js', '.scss']
extensions: ['.js', '.scss'],
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.js$/,
enforce: 'pre',
loader: 'eslint-loader',
include: path.resolve(__dirname, '../src/js'),
},
{
test: /\.js$/,
use: [
@ -48,61 +41,54 @@ module.exports = {
{
loader: 'babel-loader',
options: {
compact: true,
presets: ['env']
}
}
]
cacheDirectory: true,
presets: ['@babel/preset-env'],
},
},
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
minimize: true,
sourceMap: true
}
},
},
{
loader: 'postcss-loader',
options: {
config: {
path: path.join(__dirname, 'postcss.config.js')
}
}
plugins: [autoprefixer, cssnano],
},
},
'sass-loader',
]
],
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
options: {
'limit': 40000
}
limit: 40000,
},
},
{
test: /\.svg$/,
loader: 'svg-inline-loader'
loader: 'svg-inline-loader',
},
{
test: /\.art$/,
loader: 'art-template-loader'
}
]
loader: 'art-template-loader',
},
],
},
plugins: [
new webpack.DefinePlugin({
APLAYER_VERSION: `"${require('../package.json').version}"`,
GIT_HASH: JSON.stringify(gitRevisionPlugin.version())
GIT_HASH: JSON.stringify(gitRevisionPlugin.version()),
}),
new MiniCssExtractPlugin({
filename: '[name].min.css'
})
],
node: {
@ -110,6 +96,5 @@ module.exports = {
fs: 'empty',
net: 'empty',
tls: 'empty',
}
},
};

9800
yarn.lock

File diff suppressed because it is too large Load Diff