mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-10 11:21:36 +00:00
prettier: client
This commit is contained in:
parent
f2102a0a23
commit
3beb8905c4
74 changed files with 520 additions and 652 deletions
|
|
@ -1,7 +1,8 @@
|
|||
@font-face {
|
||||
font-family: 'absicons';
|
||||
src: url('~static/fonts/absicons/absicons.eot?2jfq33');
|
||||
src: url('~static/fonts/absicons/absicons.eot?2jfq33#iefix') format('embedded-opentype'),
|
||||
src:
|
||||
url('~static/fonts/absicons/absicons.eot?2jfq33#iefix') format('embedded-opentype'),
|
||||
url('~static/fonts/absicons/absicons.ttf?2jfq33') format('truetype'),
|
||||
url('~static/fonts/absicons/absicons.woff?2jfq33') format('woff'),
|
||||
url('~static/fonts/absicons/absicons.svg?2jfq33#absicons') format('svg');
|
||||
|
|
@ -26,81 +27,81 @@
|
|||
}
|
||||
|
||||
.icon-books-1:before {
|
||||
content: "\e905";
|
||||
content: '\e905';
|
||||
}
|
||||
|
||||
.icon-microphone-1:before {
|
||||
content: "\e902";
|
||||
content: '\e902';
|
||||
}
|
||||
|
||||
.icon-radio:before {
|
||||
content: "\e903";
|
||||
content: '\e903';
|
||||
}
|
||||
|
||||
.icon-podcast:before {
|
||||
content: "\e904";
|
||||
content: '\e904';
|
||||
}
|
||||
|
||||
.icon-audiobookshelf:before {
|
||||
content: "\e900";
|
||||
content: '\e900';
|
||||
}
|
||||
|
||||
.icon-database:before {
|
||||
content: "\e906";
|
||||
content: '\e906';
|
||||
}
|
||||
|
||||
.icon-microphone-2:before {
|
||||
content: "\e901";
|
||||
content: '\e901';
|
||||
}
|
||||
|
||||
.icon-headphones:before {
|
||||
content: "\e910";
|
||||
content: '\e910';
|
||||
}
|
||||
|
||||
.icon-music:before {
|
||||
content: "\e911";
|
||||
content: '\e911';
|
||||
}
|
||||
|
||||
.icon-video:before {
|
||||
content: "\e914";
|
||||
content: '\e914';
|
||||
}
|
||||
|
||||
.icon-microphone-3:before {
|
||||
content: "\e91e";
|
||||
content: '\e91e';
|
||||
}
|
||||
|
||||
.icon-book-1:before {
|
||||
content: "\e91f";
|
||||
content: '\e91f';
|
||||
}
|
||||
|
||||
.icon-books-2:before {
|
||||
content: "\e920";
|
||||
content: '\e920';
|
||||
}
|
||||
|
||||
.icon-file-picture:before {
|
||||
content: "\e927";
|
||||
content: '\e927';
|
||||
}
|
||||
|
||||
.icon-database-1:before {
|
||||
content: "\e964";
|
||||
content: '\e964';
|
||||
}
|
||||
|
||||
.icon-rocket:before {
|
||||
content: "\e9a5";
|
||||
content: '\e9a5';
|
||||
}
|
||||
|
||||
.icon-power:before {
|
||||
content: "\e9b5";
|
||||
content: '\e9b5';
|
||||
}
|
||||
|
||||
.icon-star:before {
|
||||
content: "\e9d9";
|
||||
content: '\e9d9';
|
||||
}
|
||||
|
||||
.icon-heart:before {
|
||||
content: "\e9da";
|
||||
content: '\e9da';
|
||||
}
|
||||
|
||||
.icon-rss:before {
|
||||
content: "\ea9b";
|
||||
}
|
||||
content: '\ea9b';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,11 +92,10 @@
|
|||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
|
||||
.tracksTable {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
|
|
@ -174,7 +173,10 @@ input[type=number] {
|
|||
}
|
||||
|
||||
.box-shadow-book {
|
||||
box-shadow: 4px 1px 8px #11111166, -4px 1px 8px #11111166, 1px -4px 8px #11111166;
|
||||
box-shadow:
|
||||
4px 1px 8px #11111166,
|
||||
-4px 1px 8px #11111166,
|
||||
1px -4px 8px #11111166;
|
||||
}
|
||||
|
||||
.shadow-height {
|
||||
|
|
@ -182,7 +184,9 @@ input[type=number] {
|
|||
}
|
||||
|
||||
.box-shadow-book3d {
|
||||
box-shadow: 4px 1px 8px #11111166, 1px -4px 8px #11111166;
|
||||
box-shadow:
|
||||
4px 1px 8px #11111166,
|
||||
1px -4px 8px #11111166;
|
||||
}
|
||||
|
||||
.box-shadow-side {
|
||||
|
|
@ -204,7 +208,6 @@ Bookshelf Label
|
|||
color: #fce3a6;
|
||||
}
|
||||
|
||||
|
||||
.cover-bg {
|
||||
width: calc(100% + 40px);
|
||||
height: calc(100% + 40px);
|
||||
|
|
@ -247,4 +250,4 @@ Bookshelf Label
|
|||
|
||||
.abs-btn:disabled::before {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,4 +52,4 @@
|
|||
text-indent: 0px !important;
|
||||
text-align: start !important;
|
||||
text-align-last: start !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,4 +45,4 @@
|
|||
|
||||
.list-group-item.exclude:not(.ghost):hover {
|
||||
background-color: rgba(223, 0, 0, 0.25);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,4 +503,4 @@ a.hlink {
|
|||
.underline {
|
||||
text-decoration: underline
|
||||
}
|
||||
`
|
||||
`
|
||||
|
|
|
|||
|
|
@ -2,247 +2,124 @@
|
|||
This is borrowed from koodo-reader https://github.com/troyeguo/koodo-reader/tree/master/src
|
||||
*/
|
||||
|
||||
export const isTitle = (
|
||||
line,
|
||||
isContainDI = false,
|
||||
isContainChapter = false,
|
||||
isContainCHAPTER = false
|
||||
) => {
|
||||
export const isTitle = (line, isContainDI = false, isContainChapter = false, isContainCHAPTER = false) => {
|
||||
return (
|
||||
line.length < 30 &&
|
||||
line.indexOf("[") === -1 &&
|
||||
line.indexOf("(") === -1 &&
|
||||
(line.startsWith("CHAPTER") ||
|
||||
line.startsWith("Chapter") ||
|
||||
line.startsWith("序章") ||
|
||||
line.startsWith("前言") ||
|
||||
line.startsWith("声明") ||
|
||||
line.startsWith("聲明") ||
|
||||
line.startsWith("写在前面的话") ||
|
||||
line.startsWith("后记") ||
|
||||
line.startsWith("楔子") ||
|
||||
line.startsWith("后序") ||
|
||||
line.startsWith("寫在前面的話") ||
|
||||
line.startsWith("後記") ||
|
||||
line.startsWith("後序") ||
|
||||
/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(
|
||||
line
|
||||
) ||
|
||||
(line.startsWith("第") && startWithDI(line)) ||
|
||||
(line.startsWith("卷") && startWithJUAN(line)) ||
|
||||
line.indexOf('[') === -1 &&
|
||||
line.indexOf('(') === -1 &&
|
||||
(line.startsWith('CHAPTER') ||
|
||||
line.startsWith('Chapter') ||
|
||||
line.startsWith('序章') ||
|
||||
line.startsWith('前言') ||
|
||||
line.startsWith('声明') ||
|
||||
line.startsWith('聲明') ||
|
||||
line.startsWith('写在前面的话') ||
|
||||
line.startsWith('后记') ||
|
||||
line.startsWith('楔子') ||
|
||||
line.startsWith('后序') ||
|
||||
line.startsWith('寫在前面的話') ||
|
||||
line.startsWith('後記') ||
|
||||
line.startsWith('後序') ||
|
||||
/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(line) ||
|
||||
(line.startsWith('第') && startWithDI(line)) ||
|
||||
(line.startsWith('卷') && startWithJUAN(line)) ||
|
||||
startWithRomanNum(line) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf("第") > -1 &&
|
||||
(line[line.indexOf("第") - 1] === " " ||
|
||||
line[line.indexOf("第") - 1] === " " ||
|
||||
line[line.indexOf("第") - 1] === "、" ||
|
||||
line[line.indexOf("第") - 1] === ":" ||
|
||||
line[line.indexOf("第") - 1] === ":") &&
|
||||
startWithDI(line.substr(line.indexOf("第")))) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf(" ") &&
|
||||
startWithNumAndSpace(line)) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf(" ") &&
|
||||
startWithNumAndSpace(line)) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf("、") &&
|
||||
startWithNumAndPause(line)) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf(":") &&
|
||||
startWithNumAndColon(line)) ||
|
||||
(!isContainDI &&
|
||||
!isContainChapter &&
|
||||
!isContainCHAPTER &&
|
||||
line.indexOf(":") &&
|
||||
startWithNumAndColon(line)))
|
||||
);
|
||||
};
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf('第') > -1 && (line[line.indexOf('第') - 1] === ' ' || line[line.indexOf('第') - 1] === ' ' || line[line.indexOf('第') - 1] === '、' || line[line.indexOf('第') - 1] === ':' || line[line.indexOf('第') - 1] === ':') && startWithDI(line.substr(line.indexOf('第')))) ||
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf(' ') && startWithNumAndSpace(line)) ||
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf(' ') && startWithNumAndSpace(line)) ||
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf('、') && startWithNumAndPause(line)) ||
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf(':') && startWithNumAndColon(line)) ||
|
||||
(!isContainDI && !isContainChapter && !isContainCHAPTER && line.indexOf(':') && startWithNumAndColon(line)))
|
||||
)
|
||||
}
|
||||
const startWithDI = (line) => {
|
||||
let keywords = [
|
||||
"章",
|
||||
"节",
|
||||
"回",
|
||||
"節",
|
||||
"卷",
|
||||
"部",
|
||||
"輯",
|
||||
"辑",
|
||||
"話",
|
||||
"集",
|
||||
"话",
|
||||
"篇",
|
||||
];
|
||||
let flag = false;
|
||||
let keywords = ['章', '节', '回', '節', '卷', '部', '輯', '辑', '話', '集', '话', '篇']
|
||||
let flag = false
|
||||
for (let i = 0; i < keywords.length; i++) {
|
||||
if (
|
||||
(line.indexOf(keywords[i]) > -1 &&
|
||||
(line[line.indexOf(keywords[i]) + 1] === " " ||
|
||||
line[line.indexOf(keywords[i]) + 1] === " " ||
|
||||
line[line.indexOf(keywords[i]) + 1] === "、" ||
|
||||
line[line.indexOf(keywords[i]) + 1] === ":" ||
|
||||
line[line.indexOf(keywords[i]) + 1] === ":")) ||
|
||||
!line[line.indexOf(keywords[i]) + 1]
|
||||
) {
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(1, line.indexOf(keywords[i])).trim()
|
||||
) ||
|
||||
/^\d+$/.test(line.substring(1, line.indexOf(keywords[i])).trim())
|
||||
) {
|
||||
flag = true;
|
||||
if ((line.indexOf(keywords[i]) > -1 && (line[line.indexOf(keywords[i]) + 1] === ' ' || line[line.indexOf(keywords[i]) + 1] === ' ' || line[line.indexOf(keywords[i]) + 1] === '、' || line[line.indexOf(keywords[i]) + 1] === ':' || line[line.indexOf(keywords[i]) + 1] === ':')) || !line[line.indexOf(keywords[i]) + 1]) {
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(1, line.indexOf(keywords[i])).trim()) || /^\d+$/.test(line.substring(1, line.indexOf(keywords[i])).trim())) {
|
||||
flag = true
|
||||
}
|
||||
if (flag) break;
|
||||
if (flag) break
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
};
|
||||
return flag
|
||||
}
|
||||
const startWithJUAN = (line) => {
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(1, line.indexOf(" "))
|
||||
) ||
|
||||
/^\d+$/.test(line.substring(1, line.indexOf(" ")))
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(1, line.indexOf(" "))
|
||||
) ||
|
||||
/^\d+$/.test(line.substring(1, line.indexOf(" ")))
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(1)
|
||||
) ||
|
||||
/^\d+$/.test(line.substring(1))
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(1, line.indexOf(' '))) || /^\d+$/.test(line.substring(1, line.indexOf(' ')))) return true
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(1, line.indexOf(' '))) || /^\d+$/.test(line.substring(1, line.indexOf(' ')))) return true
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(1)) || /^\d+$/.test(line.substring(1))) return true
|
||||
return false
|
||||
}
|
||||
const startWithRomanNum = (line) => {
|
||||
if (
|
||||
/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(
|
||||
line.substring(0, line.indexOf(" "))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(
|
||||
line.substring(0, line.indexOf("."))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(
|
||||
line.trim()
|
||||
)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
if (/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(line.substring(0, line.indexOf(' ')))) return true
|
||||
if (/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(line.substring(0, line.indexOf('.')))) return true
|
||||
if (/(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/.test(line.trim())) return true
|
||||
return false
|
||||
}
|
||||
const startWithNumAndSpace = (line) => {
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(0, line.indexOf(" "))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(0, line.indexOf(" "))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(0, line.indexOf(' ')))) return true
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(0, line.indexOf(' ')))) return true
|
||||
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(" ")))) return true;
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(" ")))) return true;
|
||||
return false;
|
||||
};
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(' ')))) return true
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(' ')))) return true
|
||||
return false
|
||||
}
|
||||
const startWithNumAndColon = (line) => {
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(0, line.indexOf(":"))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(0, line.indexOf(":"))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(0, line.indexOf(':')))) return true
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(0, line.indexOf(':')))) return true
|
||||
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(":")))) return true;
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(":")))) return true;
|
||||
return false;
|
||||
};
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(':')))) return true
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf(':')))) return true
|
||||
return false
|
||||
}
|
||||
const startWithNumAndPause = (line) => {
|
||||
if (
|
||||
/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(
|
||||
line.substring(0, line.indexOf("、"))
|
||||
)
|
||||
)
|
||||
return true;
|
||||
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf("、")))) return true;
|
||||
return false;
|
||||
};
|
||||
if (/^[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u842c]+$/.test(line.substring(0, line.indexOf('、')))) return true
|
||||
|
||||
if (/^\d+$/.test(line.substring(0, line.indexOf('、')))) return true
|
||||
return false
|
||||
}
|
||||
|
||||
class HtmlParser {
|
||||
bookDoc;
|
||||
contentList;
|
||||
contentTitleList;
|
||||
bookDoc
|
||||
contentList
|
||||
contentTitleList
|
||||
constructor(bookDoc) {
|
||||
this.bookDoc = bookDoc;
|
||||
this.contentList = [];
|
||||
this.contentTitleList = [];
|
||||
this.getContent(bookDoc);
|
||||
this.bookDoc = bookDoc
|
||||
this.contentList = []
|
||||
this.contentTitleList = []
|
||||
this.getContent(bookDoc)
|
||||
}
|
||||
getContent(bookDoc) {
|
||||
this.contentList = Array.from(
|
||||
bookDoc.querySelectorAll("h1,h2,h3,h4,h5,b,font")
|
||||
).filter((item, index) => {
|
||||
return isTitle(item.innerText.trim());
|
||||
});
|
||||
this.contentList = Array.from(bookDoc.querySelectorAll('h1,h2,h3,h4,h5,b,font')).filter((item, index) => {
|
||||
return isTitle(item.innerText.trim())
|
||||
})
|
||||
|
||||
for (let i = 0; i < this.contentList.length; i++) {
|
||||
let random = Math.floor(Math.random() * 900000) + 100000;
|
||||
let random = Math.floor(Math.random() * 900000) + 100000
|
||||
this.contentTitleList.push({
|
||||
label: this.contentList[i].innerText,
|
||||
id: "title" + random,
|
||||
href: "#title" + random,
|
||||
subitems: [],
|
||||
});
|
||||
id: 'title' + random,
|
||||
href: '#title' + random,
|
||||
subitems: []
|
||||
})
|
||||
}
|
||||
for (let i = 0; i < this.contentList.length; i++) {
|
||||
this.contentList[i].id = this.contentTitleList[i].id;
|
||||
this.contentList[i].id = this.contentTitleList[i].id
|
||||
}
|
||||
}
|
||||
getAnchoredDoc() {
|
||||
return this.bookDoc;
|
||||
return this.bookDoc
|
||||
}
|
||||
getContentList() {
|
||||
return this.contentTitleList.filter((item, index) => {
|
||||
if (index > 0) {
|
||||
return item.label !== this.contentTitleList[index - 1].label;
|
||||
return item.label !== this.contentTitleList[index - 1].label
|
||||
} else {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default HtmlParser;
|
||||
export default HtmlParser
|
||||
|
|
|
|||
|
|
@ -4,447 +4,440 @@ This is borrowed from koodo-reader https://github.com/troyeguo/koodo-reader/tree
|
|||
|
||||
function ab2str(buf) {
|
||||
if (buf instanceof ArrayBuffer) {
|
||||
buf = new Uint8Array(buf);
|
||||
buf = new Uint8Array(buf)
|
||||
}
|
||||
return new TextDecoder("utf-8").decode(buf);
|
||||
return new TextDecoder('utf-8').decode(buf)
|
||||
}
|
||||
|
||||
var domParser = new DOMParser();
|
||||
var domParser = new DOMParser()
|
||||
|
||||
class Buffer {
|
||||
capacity;
|
||||
fragment_list;
|
||||
imageArray;
|
||||
cur_fragment;
|
||||
capacity
|
||||
fragment_list
|
||||
imageArray
|
||||
cur_fragment
|
||||
constructor(capacity) {
|
||||
this.capacity = capacity;
|
||||
this.fragment_list = [];
|
||||
this.imageArray = [];
|
||||
this.cur_fragment = new Fragment(capacity);
|
||||
this.fragment_list.push(this.cur_fragment);
|
||||
this.capacity = capacity
|
||||
this.fragment_list = []
|
||||
this.imageArray = []
|
||||
this.cur_fragment = new Fragment(capacity)
|
||||
this.fragment_list.push(this.cur_fragment)
|
||||
}
|
||||
write(byte) {
|
||||
var result = this.cur_fragment.write(byte);
|
||||
var result = this.cur_fragment.write(byte)
|
||||
if (!result) {
|
||||
this.cur_fragment = new Fragment(this.capacity);
|
||||
this.fragment_list.push(this.cur_fragment);
|
||||
this.cur_fragment.write(byte);
|
||||
this.cur_fragment = new Fragment(this.capacity)
|
||||
this.fragment_list.push(this.cur_fragment)
|
||||
this.cur_fragment.write(byte)
|
||||
}
|
||||
}
|
||||
get(idx) {
|
||||
var fi = 0;
|
||||
var fi = 0
|
||||
while (fi < this.fragment_list.length) {
|
||||
var frag = this.fragment_list[fi];
|
||||
var frag = this.fragment_list[fi]
|
||||
if (idx < frag.size) {
|
||||
return frag.get(idx);
|
||||
return frag.get(idx)
|
||||
}
|
||||
idx -= frag.size;
|
||||
fi += 1;
|
||||
idx -= frag.size
|
||||
fi += 1
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
size() {
|
||||
var s = 0;
|
||||
var s = 0
|
||||
for (var i = 0; i < this.fragment_list.length; i++) {
|
||||
s += this.fragment_list[i].size;
|
||||
s += this.fragment_list[i].size
|
||||
}
|
||||
return s;
|
||||
return s
|
||||
}
|
||||
shrink() {
|
||||
var total_buffer = new Uint8Array(this.size());
|
||||
var offset = 0;
|
||||
var total_buffer = new Uint8Array(this.size())
|
||||
var offset = 0
|
||||
for (var i = 0; i < this.fragment_list.length; i++) {
|
||||
var frag = this.fragment_list[i];
|
||||
var frag = this.fragment_list[i]
|
||||
if (frag.full()) {
|
||||
total_buffer.set(frag.buffer, offset);
|
||||
total_buffer.set(frag.buffer, offset)
|
||||
} else {
|
||||
total_buffer.set(frag.buffer.slice(0, frag.size), offset);
|
||||
total_buffer.set(frag.buffer.slice(0, frag.size), offset)
|
||||
}
|
||||
offset += frag.size;
|
||||
offset += frag.size
|
||||
}
|
||||
return total_buffer;
|
||||
return total_buffer
|
||||
}
|
||||
}
|
||||
|
||||
var copagesne_uint8array = function (buffers) {
|
||||
var total_size = 0;
|
||||
var total_size = 0
|
||||
for (let i = 0; i < buffers.length; i++) {
|
||||
var buffer = buffers[i];
|
||||
total_size += buffer.length;
|
||||
var buffer = buffers[i]
|
||||
total_size += buffer.length
|
||||
}
|
||||
var total_buffer = new Uint8Array(total_size);
|
||||
var offset = 0;
|
||||
var total_buffer = new Uint8Array(total_size)
|
||||
var offset = 0
|
||||
for (let i = 0; i < buffers.length; i++) {
|
||||
buffer = buffers[i];
|
||||
total_buffer.set(buffer, offset);
|
||||
offset += buffer.length;
|
||||
buffer = buffers[i]
|
||||
total_buffer.set(buffer, offset)
|
||||
offset += buffer.length
|
||||
}
|
||||
return total_buffer;
|
||||
};
|
||||
return total_buffer
|
||||
}
|
||||
|
||||
class Fragment {
|
||||
buffer;
|
||||
capacity;
|
||||
size;
|
||||
buffer
|
||||
capacity
|
||||
size
|
||||
constructor(capacity) {
|
||||
this.buffer = new Uint8Array(capacity);
|
||||
this.capacity = capacity;
|
||||
this.size = 0;
|
||||
this.buffer = new Uint8Array(capacity)
|
||||
this.capacity = capacity
|
||||
this.size = 0
|
||||
}
|
||||
|
||||
write(byte) {
|
||||
if (this.size >= this.capacity) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
this.buffer[this.size] = byte;
|
||||
this.size += 1;
|
||||
return true;
|
||||
this.buffer[this.size] = byte
|
||||
this.size += 1
|
||||
return true
|
||||
}
|
||||
full() {
|
||||
return this.size === this.capacity;
|
||||
return this.size === this.capacity
|
||||
}
|
||||
get(idx) {
|
||||
return this.buffer[idx];
|
||||
return this.buffer[idx]
|
||||
}
|
||||
}
|
||||
|
||||
var uncompression_lz77 = function (data) {
|
||||
var length = data.length;
|
||||
var offset = 0; // Current offset into data
|
||||
var buffer = new Buffer(data.length);
|
||||
var length = data.length
|
||||
var offset = 0 // Current offset into data
|
||||
var buffer = new Buffer(data.length)
|
||||
|
||||
while (offset < length) {
|
||||
var char = data[offset];
|
||||
offset += 1;
|
||||
var char = data[offset]
|
||||
offset += 1
|
||||
|
||||
if (char === 0) {
|
||||
buffer.write(char);
|
||||
buffer.write(char)
|
||||
} else if (char <= 8) {
|
||||
for (var i = offset; i < offset + char; i++) {
|
||||
buffer.write(data[i]);
|
||||
buffer.write(data[i])
|
||||
}
|
||||
offset += char;
|
||||
offset += char
|
||||
} else if (char <= 0x7f) {
|
||||
buffer.write(char);
|
||||
buffer.write(char)
|
||||
} else if (char <= 0xbf) {
|
||||
var next = data[offset];
|
||||
offset += 1;
|
||||
var distance = (((char << 8) | next) >> 3) & 0x7ff;
|
||||
var lz_length = (next & 0x7) + 3;
|
||||
var next = data[offset]
|
||||
offset += 1
|
||||
var distance = (((char << 8) | next) >> 3) & 0x7ff
|
||||
var lz_length = (next & 0x7) + 3
|
||||
|
||||
var buffer_size = buffer.size();
|
||||
var buffer_size = buffer.size()
|
||||
for (let i = 0; i < lz_length; i++) {
|
||||
buffer.write(buffer.get(buffer_size - distance));
|
||||
buffer_size += 1;
|
||||
buffer.write(buffer.get(buffer_size - distance))
|
||||
buffer_size += 1
|
||||
}
|
||||
} else {
|
||||
buffer.write(32);
|
||||
buffer.write(char ^ 0x80);
|
||||
buffer.write(32)
|
||||
buffer.write(char ^ 0x80)
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
return buffer
|
||||
}
|
||||
|
||||
class MobiFile {
|
||||
view;
|
||||
buffer;
|
||||
offset;
|
||||
header;
|
||||
palm_header;
|
||||
mobi_header;
|
||||
reclist;
|
||||
view
|
||||
buffer
|
||||
offset
|
||||
header
|
||||
palm_header
|
||||
mobi_header
|
||||
reclist
|
||||
constructor(data) {
|
||||
this.view = new DataView(data);
|
||||
this.buffer = this.view.buffer;
|
||||
this.offset = 0;
|
||||
this.header = null;
|
||||
this.view = new DataView(data)
|
||||
this.buffer = this.view.buffer
|
||||
this.offset = 0
|
||||
this.header = null
|
||||
}
|
||||
|
||||
parse() { }
|
||||
parse() {}
|
||||
|
||||
getUint8() {
|
||||
var v = this.view.getUint8(this.offset);
|
||||
this.offset += 1;
|
||||
return v;
|
||||
var v = this.view.getUint8(this.offset)
|
||||
this.offset += 1
|
||||
return v
|
||||
}
|
||||
|
||||
getUint16() {
|
||||
var v = this.view.getUint16(this.offset);
|
||||
this.offset += 2;
|
||||
return v;
|
||||
var v = this.view.getUint16(this.offset)
|
||||
this.offset += 2
|
||||
return v
|
||||
}
|
||||
|
||||
getUint32() {
|
||||
var v = this.view.getUint32(this.offset);
|
||||
this.offset += 4;
|
||||
return v;
|
||||
var v = this.view.getUint32(this.offset)
|
||||
this.offset += 4
|
||||
return v
|
||||
}
|
||||
|
||||
getStr(size) {
|
||||
var v = ab2str(this.buffer.slice(this.offset, this.offset + size));
|
||||
this.offset += size;
|
||||
return v;
|
||||
var v = ab2str(this.buffer.slice(this.offset, this.offset + size))
|
||||
this.offset += size
|
||||
return v
|
||||
}
|
||||
|
||||
skip(size) {
|
||||
this.offset += size;
|
||||
this.offset += size
|
||||
}
|
||||
|
||||
setoffset(_of) {
|
||||
this.offset = _of;
|
||||
this.offset = _of
|
||||
}
|
||||
|
||||
get_record_extrasize(data, flags) {
|
||||
var pos = data.length - 1;
|
||||
var extra = 0;
|
||||
var pos = data.length - 1
|
||||
var extra = 0
|
||||
for (var i = 15; i > 0; i--) {
|
||||
if (flags & (1 << i)) {
|
||||
var res = this.buffer_get_varlen(data, pos);
|
||||
var size = res[0];
|
||||
var l = res[1];
|
||||
pos = res[2];
|
||||
pos -= size - l;
|
||||
extra += size;
|
||||
var res = this.buffer_get_varlen(data, pos)
|
||||
var size = res[0]
|
||||
var l = res[1]
|
||||
pos = res[2]
|
||||
pos -= size - l
|
||||
extra += size
|
||||
}
|
||||
}
|
||||
if (flags & 1) {
|
||||
var a = data[pos];
|
||||
extra += (a & 0x3) + 1;
|
||||
var a = data[pos]
|
||||
extra += (a & 0x3) + 1
|
||||
}
|
||||
return extra;
|
||||
return extra
|
||||
}
|
||||
|
||||
// data should be uint8array
|
||||
buffer_get_varlen(data, pos) {
|
||||
var l = 0;
|
||||
var size = 0;
|
||||
var byte_count = 0;
|
||||
var mask = 0x7f;
|
||||
var stop_flag = 0x80;
|
||||
var shift = 0;
|
||||
var l = 0
|
||||
var size = 0
|
||||
var byte_count = 0
|
||||
var mask = 0x7f
|
||||
var stop_flag = 0x80
|
||||
var shift = 0
|
||||
for (var i = 0; ; i++) {
|
||||
var byte = data[pos];
|
||||
size |= (byte & mask) << shift;
|
||||
shift += 7;
|
||||
l += 1;
|
||||
byte_count += 1;
|
||||
pos -= 1;
|
||||
var byte = data[pos]
|
||||
size |= (byte & mask) << shift
|
||||
shift += 7
|
||||
l += 1
|
||||
byte_count += 1
|
||||
pos -= 1
|
||||
|
||||
var to_stop = byte & stop_flag;
|
||||
var to_stop = byte & stop_flag
|
||||
if (byte_count >= 4 || to_stop > 0) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
return [size, l, pos];
|
||||
return [size, l, pos]
|
||||
}
|
||||
// 读出文本内容
|
||||
read_text() {
|
||||
var text_end = this.palm_header.record_count;
|
||||
var buffers = [];
|
||||
var text_end = this.palm_header.record_count
|
||||
var buffers = []
|
||||
for (var i = 1; i <= text_end; i++) {
|
||||
buffers.push(this.read_text_record(i));
|
||||
buffers.push(this.read_text_record(i))
|
||||
}
|
||||
var all = copagesne_uint8array(buffers);
|
||||
return ab2str(all);
|
||||
var all = copagesne_uint8array(buffers)
|
||||
return ab2str(all)
|
||||
}
|
||||
|
||||
read_text_record(i) {
|
||||
var flags = this.mobi_header.extra_flags;
|
||||
var begin = this.reclist[i].offset;
|
||||
var end = this.reclist[i + 1].offset;
|
||||
var flags = this.mobi_header.extra_flags
|
||||
var begin = this.reclist[i].offset
|
||||
var end = this.reclist[i + 1].offset
|
||||
|
||||
var data = new Uint8Array(this.buffer.slice(begin, end));
|
||||
var ex = this.get_record_extrasize(data, flags);
|
||||
var data = new Uint8Array(this.buffer.slice(begin, end))
|
||||
var ex = this.get_record_extrasize(data, flags)
|
||||
|
||||
data = new Uint8Array(this.buffer.slice(begin, end - ex));
|
||||
data = new Uint8Array(this.buffer.slice(begin, end - ex))
|
||||
if (this.palm_header.compression === 2) {
|
||||
var buffer = uncompression_lz77(data);
|
||||
return buffer.shrink();
|
||||
var buffer = uncompression_lz77(data)
|
||||
return buffer.shrink()
|
||||
} else {
|
||||
return data;
|
||||
return data
|
||||
}
|
||||
}
|
||||
// 从buffer中读出image
|
||||
read_image(idx) {
|
||||
var first_image_idx = this.mobi_header.first_image_idx;
|
||||
var begin = this.reclist[first_image_idx + idx].offset;
|
||||
var end = this.reclist[first_image_idx + idx + 1].offset;
|
||||
var data = new Uint8Array(this.buffer.slice(begin, end));
|
||||
return new Blob([data.buffer]);
|
||||
var first_image_idx = this.mobi_header.first_image_idx
|
||||
var begin = this.reclist[first_image_idx + idx].offset
|
||||
var end = this.reclist[first_image_idx + idx + 1].offset
|
||||
var data = new Uint8Array(this.buffer.slice(begin, end))
|
||||
return new Blob([data.buffer])
|
||||
}
|
||||
|
||||
load() {
|
||||
this.header = this.load_pdbheader();
|
||||
this.reclist = this.load_reclist();
|
||||
this.load_record0();
|
||||
this.header = this.load_pdbheader()
|
||||
this.reclist = this.load_reclist()
|
||||
this.load_record0()
|
||||
}
|
||||
|
||||
load_pdbheader() {
|
||||
var header = {};
|
||||
header.name = this.getStr(32);
|
||||
header.attr = this.getUint16();
|
||||
header.version = this.getUint16();
|
||||
header.ctime = this.getUint32();
|
||||
header.mtime = this.getUint32();
|
||||
header.btime = this.getUint32();
|
||||
header.mod_num = this.getUint32();
|
||||
header.appinfo_offset = this.getUint32();
|
||||
header.sortinfo_offset = this.getUint32();
|
||||
header.type = this.getStr(4);
|
||||
header.creator = this.getStr(4);
|
||||
header.uid = this.getUint32();
|
||||
header.next_rec = this.getUint32();
|
||||
header.record_num = this.getUint16();
|
||||
return header;
|
||||
var header = {}
|
||||
header.name = this.getStr(32)
|
||||
header.attr = this.getUint16()
|
||||
header.version = this.getUint16()
|
||||
header.ctime = this.getUint32()
|
||||
header.mtime = this.getUint32()
|
||||
header.btime = this.getUint32()
|
||||
header.mod_num = this.getUint32()
|
||||
header.appinfo_offset = this.getUint32()
|
||||
header.sortinfo_offset = this.getUint32()
|
||||
header.type = this.getStr(4)
|
||||
header.creator = this.getStr(4)
|
||||
header.uid = this.getUint32()
|
||||
header.next_rec = this.getUint32()
|
||||
header.record_num = this.getUint16()
|
||||
return header
|
||||
}
|
||||
|
||||
load_reclist() {
|
||||
var reclist = [];
|
||||
var reclist = []
|
||||
for (var i = 0; i < this.header.record_num; i++) {
|
||||
var record = {};
|
||||
record.offset = this.getUint32();
|
||||
var record = {}
|
||||
record.offset = this.getUint32()
|
||||
// TODO(zz) change
|
||||
record.attr = this.getUint32();
|
||||
reclist.push(record);
|
||||
record.attr = this.getUint32()
|
||||
reclist.push(record)
|
||||
}
|
||||
return reclist;
|
||||
return reclist
|
||||
}
|
||||
load_record0() {
|
||||
this.palm_header = this.load_record0_header();
|
||||
this.mobi_header = this.load_mobi_header();
|
||||
this.palm_header = this.load_record0_header()
|
||||
this.mobi_header = this.load_mobi_header()
|
||||
}
|
||||
|
||||
load_record0_header() {
|
||||
var p_header = {};
|
||||
var first_record = this.reclist[0];
|
||||
this.setoffset(first_record.offset);
|
||||
var p_header = {}
|
||||
var first_record = this.reclist[0]
|
||||
this.setoffset(first_record.offset)
|
||||
|
||||
p_header.compression = this.getUint16();
|
||||
this.skip(2);
|
||||
p_header.text_length = this.getUint32();
|
||||
p_header.record_count = this.getUint16();
|
||||
p_header.record_size = this.getUint16();
|
||||
p_header.encryption_type = this.getUint16();
|
||||
this.skip(2);
|
||||
p_header.compression = this.getUint16()
|
||||
this.skip(2)
|
||||
p_header.text_length = this.getUint32()
|
||||
p_header.record_count = this.getUint16()
|
||||
p_header.record_size = this.getUint16()
|
||||
p_header.encryption_type = this.getUint16()
|
||||
this.skip(2)
|
||||
|
||||
return p_header;
|
||||
return p_header
|
||||
}
|
||||
|
||||
load_mobi_header() {
|
||||
var mobi_header = {};
|
||||
var mobi_header = {}
|
||||
|
||||
var start_offset = this.offset;
|
||||
var start_offset = this.offset
|
||||
|
||||
mobi_header.identifier = this.getUint32();
|
||||
mobi_header.header_length = this.getUint32();
|
||||
mobi_header.mobi_type = this.getUint32();
|
||||
mobi_header.text_encoding = this.getUint32();
|
||||
mobi_header.uid = this.getUint32();
|
||||
mobi_header.generator_version = this.getUint32();
|
||||
mobi_header.identifier = this.getUint32()
|
||||
mobi_header.header_length = this.getUint32()
|
||||
mobi_header.mobi_type = this.getUint32()
|
||||
mobi_header.text_encoding = this.getUint32()
|
||||
mobi_header.uid = this.getUint32()
|
||||
mobi_header.generator_version = this.getUint32()
|
||||
|
||||
this.skip(40);
|
||||
this.skip(40)
|
||||
|
||||
mobi_header.first_nonbook_index = this.getUint32();
|
||||
mobi_header.full_name_offset = this.getUint32();
|
||||
mobi_header.full_name_length = this.getUint32();
|
||||
mobi_header.first_nonbook_index = this.getUint32()
|
||||
mobi_header.full_name_offset = this.getUint32()
|
||||
mobi_header.full_name_length = this.getUint32()
|
||||
|
||||
mobi_header.language = this.getUint32();
|
||||
mobi_header.input_language = this.getUint32();
|
||||
mobi_header.output_language = this.getUint32();
|
||||
mobi_header.min_version = this.getUint32();
|
||||
mobi_header.first_image_idx = this.getUint32();
|
||||
mobi_header.language = this.getUint32()
|
||||
mobi_header.input_language = this.getUint32()
|
||||
mobi_header.output_language = this.getUint32()
|
||||
mobi_header.min_version = this.getUint32()
|
||||
mobi_header.first_image_idx = this.getUint32()
|
||||
|
||||
mobi_header.huff_rec_index = this.getUint32();
|
||||
mobi_header.huff_rec_count = this.getUint32();
|
||||
mobi_header.datp_rec_index = this.getUint32();
|
||||
mobi_header.datp_rec_count = this.getUint32();
|
||||
mobi_header.huff_rec_index = this.getUint32()
|
||||
mobi_header.huff_rec_count = this.getUint32()
|
||||
mobi_header.datp_rec_index = this.getUint32()
|
||||
mobi_header.datp_rec_count = this.getUint32()
|
||||
|
||||
mobi_header.exth_flags = this.getUint32();
|
||||
mobi_header.exth_flags = this.getUint32()
|
||||
|
||||
this.skip(36);
|
||||
this.skip(36)
|
||||
|
||||
mobi_header.drm_offset = this.getUint32();
|
||||
mobi_header.drm_count = this.getUint32();
|
||||
mobi_header.drm_size = this.getUint32();
|
||||
mobi_header.drm_flags = this.getUint32();
|
||||
mobi_header.drm_offset = this.getUint32()
|
||||
mobi_header.drm_count = this.getUint32()
|
||||
mobi_header.drm_size = this.getUint32()
|
||||
mobi_header.drm_flags = this.getUint32()
|
||||
|
||||
this.skip(8);
|
||||
this.skip(8)
|
||||
|
||||
// TODO (zz) fdst_index
|
||||
this.skip(4);
|
||||
this.skip(4)
|
||||
|
||||
this.skip(46);
|
||||
this.skip(46)
|
||||
|
||||
mobi_header.extra_flags = this.getUint16();
|
||||
mobi_header.extra_flags = this.getUint16()
|
||||
|
||||
this.setoffset(start_offset + mobi_header.header_length);
|
||||
this.setoffset(start_offset + mobi_header.header_length)
|
||||
|
||||
return mobi_header;
|
||||
return mobi_header
|
||||
}
|
||||
load_exth_header() {
|
||||
// TODO
|
||||
return {};
|
||||
return {}
|
||||
}
|
||||
extractContent(s) {
|
||||
var span = document.createElement("span");
|
||||
span.innerHTML = s;
|
||||
return span.textContent || span.innerText;
|
||||
var span = document.createElement('span')
|
||||
span.innerHTML = s
|
||||
return span.textContent || span.innerText
|
||||
}
|
||||
render(isElectron = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.load();
|
||||
var content = this.read_text();
|
||||
var bookDoc = domParser.parseFromString(content, "text/html")
|
||||
.documentElement;
|
||||
let lines = Array.from(
|
||||
bookDoc.querySelectorAll("p,b,font,h3,h2,h1")
|
||||
);
|
||||
let parseContent = [];
|
||||
this.load()
|
||||
var content = this.read_text()
|
||||
var bookDoc = domParser.parseFromString(content, 'text/html').documentElement
|
||||
let lines = Array.from(bookDoc.querySelectorAll('p,b,font,h3,h2,h1'))
|
||||
let parseContent = []
|
||||
for (let i = 0, len = lines.length; i < len - 1; i++) {
|
||||
lines[i].innerText &&
|
||||
lines[i].innerText !== parseContent[parseContent.length - 1] &&
|
||||
parseContent.push(lines[i].innerText);
|
||||
let imgDoms = lines[i].getElementsByTagName("img");
|
||||
lines[i].innerText && lines[i].innerText !== parseContent[parseContent.length - 1] && parseContent.push(lines[i].innerText)
|
||||
let imgDoms = lines[i].getElementsByTagName('img')
|
||||
if (imgDoms.length > 0) {
|
||||
for (let i = 0; i < imgDoms.length; i++) {
|
||||
parseContent.push("#image");
|
||||
parseContent.push('#image')
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleImage = async () => {
|
||||
var imgDoms = bookDoc.getElementsByTagName("img");
|
||||
parseContent.push("~image");
|
||||
var imgDoms = bookDoc.getElementsByTagName('img')
|
||||
parseContent.push('~image')
|
||||
for (let i = 0; i < imgDoms.length; i++) {
|
||||
const src = await this.render_image(imgDoms, i);
|
||||
parseContent.push(
|
||||
src + " " + imgDoms[i].width + " " + imgDoms[i].height
|
||||
);
|
||||
const src = await this.render_image(imgDoms, i)
|
||||
parseContent.push(src + ' ' + imgDoms[i].width + ' ' + imgDoms[i].height)
|
||||
}
|
||||
if (imgDoms.length > 200 || !isElectron) {
|
||||
resolve(bookDoc);
|
||||
resolve(bookDoc)
|
||||
} else {
|
||||
resolve(parseContent.join("\n \n"));
|
||||
resolve(parseContent.join('\n \n'))
|
||||
}
|
||||
};
|
||||
handleImage();
|
||||
});
|
||||
}
|
||||
handleImage()
|
||||
})
|
||||
}
|
||||
render_image = (imgDoms, i) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var imgDom = imgDoms[i];
|
||||
var idx = +imgDom.getAttribute("recindex");
|
||||
var blob = this.read_image(idx - 1);
|
||||
var imgReader = new FileReader();
|
||||
var imgDom = imgDoms[i]
|
||||
var idx = +imgDom.getAttribute('recindex')
|
||||
var blob = this.read_image(idx - 1)
|
||||
var imgReader = new FileReader()
|
||||
imgReader.onload = (e) => {
|
||||
imgDom.src = e.target?.result;
|
||||
resolve(e.target?.result);
|
||||
};
|
||||
imgDom.src = e.target?.result
|
||||
resolve(e.target?.result)
|
||||
}
|
||||
imgReader.onerror = function (err) {
|
||||
reject(err);
|
||||
};
|
||||
imgReader.readAsDataURL(blob);
|
||||
});
|
||||
};
|
||||
reject(err)
|
||||
}
|
||||
imgReader.readAsDataURL(blob)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default MobiFile;
|
||||
export default MobiFile
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@
|
|||
}
|
||||
|
||||
.material-symbols.fill {
|
||||
font-variation-settings:
|
||||
'FILL' 1
|
||||
font-variation-settings: 'FILL' 1;
|
||||
}
|
||||
|
||||
/* cyrillic-ext */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@tailwind utilities;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
max-height: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.menu-enter,
|
||||
.menu-leave-active {
|
||||
transform: translateY(-15px);
|
||||
|
|
@ -70,7 +68,6 @@
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
.list-complete-item {
|
||||
transition: all 0.8s ease;
|
||||
}
|
||||
|
|
@ -83,4 +80,4 @@
|
|||
|
||||
.list-complete-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ trix-toolbar .trix-button--icon::before {
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
opacity: 0.6;
|
||||
content: "";
|
||||
content: '';
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
|
@ -209,7 +209,9 @@ trix-toolbar .trix-dialog {
|
|||
font-size: 0.75em;
|
||||
padding: 15px 10px;
|
||||
background: rgb(48, 48, 48);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow:
|
||||
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgb(112, 112, 112);
|
||||
border-radius: 5px;
|
||||
z-index: 5;
|
||||
|
|
@ -230,7 +232,7 @@ trix-toolbar .trix-input--dialog {
|
|||
}
|
||||
|
||||
trix-toolbar .trix-input--dialog.validate:invalid {
|
||||
box-shadow: #F00 0px 0px 1.5px 1px;
|
||||
box-shadow: #f00 0px 0px 1.5px 1px;
|
||||
}
|
||||
|
||||
trix-toolbar .trix-button--dialog {
|
||||
|
|
@ -317,7 +319,7 @@ trix-editor .attachment__progress {
|
|||
transition: opacity 200ms ease-in;
|
||||
}
|
||||
|
||||
trix-editor .attachment__progress[value="100"] {
|
||||
trix-editor .attachment__progress[value='100'] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +401,7 @@ trix-editor .trix-button--remove::before {
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
opacity: 0.7;
|
||||
content: "";
|
||||
content: '';
|
||||
background-image: url(data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.4L17.6%205%2012%2010.6%206.4%205%205%206.4l5.6%205.6L5%2017.6%206.4%2019l5.6-5.6%205.6%205.6%201.4-1.4-5.6-5.6z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
|
@ -467,8 +469,8 @@ trix-editor .attachment__metadata .attachment__size {
|
|||
padding-left: 0.6em;
|
||||
}
|
||||
|
||||
.trix-content [dir=rtl] blockquote,
|
||||
.trix-content blockquote[dir=rtl] {
|
||||
.trix-content [dir='rtl'] blockquote,
|
||||
.trix-content blockquote[dir='rtl'] {
|
||||
border-width: 0;
|
||||
border-right-width: 0.3em;
|
||||
margin-right: 0.3em;
|
||||
|
|
@ -479,7 +481,7 @@ trix-editor .attachment__metadata .attachment__size {
|
|||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.trix-content [dir=rtl] li {
|
||||
.trix-content [dir='rtl'] li {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
|
|
@ -520,7 +522,7 @@ trix-editor .attachment__metadata .attachment__size {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.trix-content .attachment__caption .attachment__name+.attachment__size::before {
|
||||
.trix-content .attachment__caption .attachment__name + .attachment__size::before {
|
||||
content: ' · ';
|
||||
}
|
||||
|
||||
|
|
@ -560,4 +562,4 @@ trix-editor .attachment__metadata .attachment__size {
|
|||
.trix-content .attachment-gallery.attachment-gallery--4 .attachment {
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,7 +643,6 @@ export default {
|
|||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
#toolbar {
|
||||
box-shadow: 0px 8px 6px #111111aa;
|
||||
|
|
|
|||
|
|
@ -39,4 +39,4 @@ export default {
|
|||
color: white;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -68,4 +68,4 @@ export default {
|
|||
this.width = this.$refs.wrapper.clientWidth
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -43,4 +43,4 @@ export default {
|
|||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -86,4 +86,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -77,4 +77,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -175,4 +175,3 @@ export default {
|
|||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -62,4 +62,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -48,4 +48,4 @@ export default {
|
|||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -103,4 +103,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -132,4 +132,3 @@ export default {
|
|||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -160,4 +160,4 @@ export default {
|
|||
this.$eventBus.$off('showing-prompt', this.showingPrompt)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -90,4 +90,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -55,4 +55,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -300,4 +300,4 @@ export default {
|
|||
.tab.tab-selected {
|
||||
height: 41px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -141,4 +141,4 @@ export default {
|
|||
this.setLastEpisodeCheckInput()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -51,4 +51,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -185,8 +185,6 @@ export default {
|
|||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.dir-item.dir-selected {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
|
|
|
|||
|
|
@ -157,4 +157,4 @@ export default {
|
|||
this.init()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -53,4 +53,4 @@ export default {
|
|||
this.init()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -99,4 +99,4 @@ export default {
|
|||
.queue-item-row-content {
|
||||
max-width: calc(100% - 48px - 128px);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -54,4 +54,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -133,4 +133,3 @@ export default {
|
|||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -121,4 +121,3 @@ export default {
|
|||
background-color: #2f2f2f;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -218,4 +218,4 @@ export default {
|
|||
window.removeEventListener('resize', this.windowResize)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -80,4 +80,4 @@ export default {
|
|||
this.el.remove()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -136,4 +136,4 @@ export default {
|
|||
.ebook-viewer {
|
||||
height: calc(100% - 96px);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ export default {
|
|||
let txtWidth = ctx.measureText(text).width
|
||||
while (txtWidth > maxWidth) {
|
||||
console.warn(`Text "${text}" is greater than max width ${maxWidth} (width:${txtWidth})`)
|
||||
if (text.endsWith('...')) text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
if (text.endsWith('...'))
|
||||
text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
else text = text.slice(0, -3) // First check remove last 3 chars
|
||||
text += '...'
|
||||
txtWidth = ctx.measureText(text).width
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ export default {
|
|||
let txtWidth = ctx.measureText(text).width
|
||||
while (txtWidth > maxWidth) {
|
||||
console.warn(`Text "${text}" is greater than max width ${maxWidth} (width:${txtWidth})`)
|
||||
if (text.endsWith('...')) text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
if (text.endsWith('...'))
|
||||
text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
else text = text.slice(0, -3) // First check remove last 3 chars
|
||||
text += '...'
|
||||
txtWidth = ctx.measureText(text).width
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ export default {
|
|||
let txtWidth = ctx.measureText(text).width
|
||||
while (txtWidth > maxWidth) {
|
||||
console.warn(`Text "${text}" is greater than max width ${maxWidth} (width:${txtWidth})`)
|
||||
if (text.endsWith('...')) text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
if (text.endsWith('...'))
|
||||
text = text.slice(0, -4) // Repeated checks remove 1 char at a time
|
||||
else text = text.slice(0, -3) // First check remove last 3 chars
|
||||
text += '...'
|
||||
txtWidth = ctx.measureText(text).width
|
||||
|
|
|
|||
|
|
@ -117,7 +117,9 @@ export default {
|
|||
background-color: #272727;
|
||||
border-radius: 4px;
|
||||
color: transparent;
|
||||
transition: color, background-color 0.5s ease;
|
||||
transition:
|
||||
color,
|
||||
background-color 0.5s ease;
|
||||
}
|
||||
|
||||
.custom-provider-api-key:hover {
|
||||
|
|
|
|||
|
|
@ -57,4 +57,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -214,4 +214,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -169,4 +169,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -75,4 +75,4 @@ export default {
|
|||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -119,4 +119,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -55,4 +55,4 @@ input {
|
|||
input:read-only {
|
||||
background-color: #444;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -40,4 +40,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -34,4 +34,4 @@ export default {
|
|||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -72,4 +72,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -83,4 +83,4 @@ input[type='range']:focus::-moz-range-thumb {
|
|||
outline: 3px solid #6b6b6b;
|
||||
outline-offset: 0.125rem;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -70,4 +70,4 @@ export default {
|
|||
mounted() {},
|
||||
beforeDestroy() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -57,4 +57,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -50,4 +50,4 @@ textarea:read-only {
|
|||
color: #aaa;
|
||||
background-color: #444;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -39,4 +39,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -82,4 +82,4 @@ export default {
|
|||
button.toggle-btn:disabled::before {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -283,4 +283,4 @@ export default {
|
|||
.trix_container .trix-content {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -248,4 +248,4 @@ export default {
|
|||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -23,4 +23,4 @@ export default {
|
|||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -108,4 +108,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@ export default {
|
|||
document.body.classList.add('no-bars')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ export default function ({ store, redirect, route, app }) {
|
|||
}
|
||||
return redirect(`/login?redirect=${encodeURIComponent(route.fullPath)}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export default {
|
|||
|
||||
var firstBookPath = Path.dirname(firstBookFile.filepath)
|
||||
|
||||
var dirs = firstBookPath.split('/').filter(d => !!d && d !== '.')
|
||||
var dirs = firstBookPath.split('/').filter((d) => !!d && d !== '.')
|
||||
if (dirs.length) {
|
||||
audiobook.title = dirs.pop()
|
||||
if (dirs.length > 1) {
|
||||
|
|
@ -189,7 +189,7 @@ export default {
|
|||
var firstAudioFile = podcast.itemFiles[0]
|
||||
if (!firstAudioFile.filepath) return podcast // No path
|
||||
var firstPath = Path.dirname(firstAudioFile.filepath)
|
||||
var dirs = firstPath.split('/').filter(d => !!d && d !== '.')
|
||||
var dirs = firstPath.split('/').filter((d) => !!d && d !== '.')
|
||||
if (dirs.length) {
|
||||
podcast.title = dirs.length > 1 ? dirs[1] : dirs[0]
|
||||
} else {
|
||||
|
|
@ -212,13 +212,15 @@ export default {
|
|||
}
|
||||
var ignoredFiles = itemData.ignoredFiles
|
||||
var index = 1
|
||||
var items = itemData.items.filter((ab) => {
|
||||
if (!ab.itemFiles.length) {
|
||||
if (ab.otherFiles.length) ignoredFiles = ignoredFiles.concat(ab.otherFiles)
|
||||
if (ab.ignoredFiles.length) ignoredFiles = ignoredFiles.concat(ab.ignoredFiles)
|
||||
}
|
||||
return ab.itemFiles.length
|
||||
}).map(ab => this.cleanItem(ab, mediaType, index++))
|
||||
var items = itemData.items
|
||||
.filter((ab) => {
|
||||
if (!ab.itemFiles.length) {
|
||||
if (ab.otherFiles.length) ignoredFiles = ignoredFiles.concat(ab.otherFiles)
|
||||
if (ab.ignoredFiles.length) ignoredFiles = ignoredFiles.concat(ab.ignoredFiles)
|
||||
}
|
||||
return ab.itemFiles.length
|
||||
})
|
||||
.map((ab) => this.cleanItem(ab, mediaType, index++))
|
||||
return {
|
||||
items,
|
||||
ignoredFiles
|
||||
|
|
@ -259,7 +261,7 @@ export default {
|
|||
|
||||
otherFiles.forEach((file) => {
|
||||
var dir = Path.dirname(file.filepath)
|
||||
var findItem = Object.values(itemMap).find(b => dir.startsWith(b.path))
|
||||
var findItem = Object.values(itemMap).find((b) => dir.startsWith(b.path))
|
||||
if (findItem) {
|
||||
findItem.otherFiles.push(file)
|
||||
} else {
|
||||
|
|
@ -270,18 +272,18 @@ export default {
|
|||
var items = []
|
||||
var index = 1
|
||||
// If book media type and all files are audio files then treat each one as an audiobook
|
||||
if (itemMap[''] && !otherFiles.length && mediaType === 'book' && !itemMap[''].itemFiles.some(f => f.filetype !== 'audio')) {
|
||||
if (itemMap[''] && !otherFiles.length && mediaType === 'book' && !itemMap[''].itemFiles.some((f) => f.filetype !== 'audio')) {
|
||||
items = itemMap[''].itemFiles.map((audioFile) => {
|
||||
return this.cleanItem({ itemFiles: [audioFile], otherFiles: [], ignoredFiles: [] }, mediaType, index++)
|
||||
})
|
||||
} else {
|
||||
items = Object.values(itemMap).map(i => this.cleanItem(i, mediaType, index++))
|
||||
items = Object.values(itemMap).map((i) => this.cleanItem(i, mediaType, index++))
|
||||
}
|
||||
|
||||
return {
|
||||
items,
|
||||
ignoredFiles: ignoredFiles
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,4 +40,4 @@ export default {
|
|||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@ export default {
|
|||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { buildCastLoadRequest, castLoadMedia } from "./castUtils"
|
||||
import { buildCastLoadRequest, castLoadMedia } from './castUtils'
|
||||
import EventEmitter from 'events'
|
||||
|
||||
export default class CastPlayer extends EventEmitter {
|
||||
|
|
@ -37,8 +37,7 @@ export default class CastPlayer extends EventEmitter {
|
|||
initialize() {
|
||||
this.player = this.ctx.$root.castPlayer
|
||||
this.playerController = this.ctx.$root.castPlayerController
|
||||
this.playerController.addEventListener(
|
||||
cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, this.evtMediaInfoChanged.bind(this))
|
||||
this.playerController.addEventListener(cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, this.evtMediaInfoChanged.bind(this))
|
||||
}
|
||||
|
||||
evtMediaInfoChanged() {
|
||||
|
|
@ -143,4 +142,4 @@ export default class CastPlayer extends EventEmitter {
|
|||
this.player.volumeLevel = volume
|
||||
this.playerController.setVolumeLevel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
timeoutRetry: {
|
||||
maxNumRetry: 4,
|
||||
retryDelayMs: 0,
|
||||
maxRetryDelayMs: 0,
|
||||
maxRetryDelayMs: 0
|
||||
},
|
||||
errorRetry: {
|
||||
maxNumRetry: 8,
|
||||
|
|
@ -160,7 +160,7 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
}
|
||||
return retry
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
|
||||
setDirectPlay() {
|
||||
// Set initial track and track time offset
|
||||
var trackIndex = this.audioTracks.findIndex(t => this.startTime >= t.startOffset && this.startTime < (t.startOffset + t.duration))
|
||||
var trackIndex = this.audioTracks.findIndex((t) => this.startTime >= t.startOffset && this.startTime < t.startOffset + t.duration)
|
||||
this.currentTrackIndex = trackIndex >= 0 ? trackIndex : 0
|
||||
|
||||
this.loadCurrentTrack()
|
||||
|
|
@ -270,7 +270,7 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
// Seeking Direct play
|
||||
if (time < this.currentTrack.startOffset || time > this.currentTrack.startOffset + this.currentTrack.duration) {
|
||||
// Change Track
|
||||
var trackIndex = this.audioTracks.findIndex(t => time >= t.startOffset && time < (t.startOffset + t.duration))
|
||||
var trackIndex = this.audioTracks.findIndex((t) => time >= t.startOffset && time < t.startOffset + t.duration)
|
||||
if (trackIndex >= 0) {
|
||||
this.startTime = time
|
||||
this.currentTrackIndex = trackIndex
|
||||
|
|
@ -293,7 +293,6 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
this.player.volume = volume
|
||||
}
|
||||
|
||||
|
||||
// Utils
|
||||
isValidDuration(duration) {
|
||||
if (duration && !isNaN(duration) && duration !== Number.POSITIVE_INFINITY && duration !== Number.NEGATIVE_INFINITY) {
|
||||
|
|
@ -338,4 +337,4 @@ export default class LocalAudioPlayer extends EventEmitter {
|
|||
var last = bufferedRanges[bufferedRanges.length - 1]
|
||||
return last.end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
export default (ctx) => {
|
||||
var sendInit = async (castContext) => {
|
||||
// Fetch background covers for chromecast (temp)
|
||||
var covers = await ctx.$axios.$get(`/api/libraries/${ctx.$store.state.libraries.currentLibraryId}/items?limit=40&minified=1`).then((data) => {
|
||||
return data.results.filter((b) => b.media.coverPath).map((libraryItem) => {
|
||||
var coverUrl = ctx.$store.getters['globals/getLibraryItemCoverSrc'](libraryItem)
|
||||
if (process.env.NODE_ENV === 'development') return coverUrl
|
||||
return `${window.location.origin}${coverUrl}`
|
||||
var covers = await ctx.$axios
|
||||
.$get(`/api/libraries/${ctx.$store.state.libraries.currentLibraryId}/items?limit=40&minified=1`)
|
||||
.then((data) => {
|
||||
return data.results
|
||||
.filter((b) => b.media.coverPath)
|
||||
.map((libraryItem) => {
|
||||
var coverUrl = ctx.$store.getters['globals/getLibraryItemCoverSrc'](libraryItem)
|
||||
if (process.env.NODE_ENV === 'development') return coverUrl
|
||||
return `${window.location.origin}${coverUrl}`
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('failed to fetch books', error)
|
||||
return null
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.error('failed to fetch books', error)
|
||||
return null
|
||||
})
|
||||
|
||||
// Custom message to receiver
|
||||
var castSession = castContext.getCurrentSession()
|
||||
|
|
@ -24,40 +29,38 @@ export default (ctx) => {
|
|||
castContext.setOptions({
|
||||
receiverApplicationId: process.env.chromecastReceiver,
|
||||
autoJoinPolicy: chrome.cast ? chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED : null
|
||||
});
|
||||
})
|
||||
|
||||
castContext.addEventListener(
|
||||
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
||||
(event) => {
|
||||
console.log('Session state changed event', event)
|
||||
castContext.addEventListener(cast.framework.CastContextEventType.SESSION_STATE_CHANGED, (event) => {
|
||||
console.log('Session state changed event', event)
|
||||
|
||||
switch (event.sessionState) {
|
||||
case cast.framework.SessionState.SESSION_STARTED:
|
||||
console.log('[chromecast] CAST SESSION STARTED')
|
||||
switch (event.sessionState) {
|
||||
case cast.framework.SessionState.SESSION_STARTED:
|
||||
console.log('[chromecast] CAST SESSION STARTED')
|
||||
|
||||
ctx.$store.commit('globals/setCasting', true)
|
||||
sendInit(castContext)
|
||||
ctx.$store.commit('globals/setCasting', true)
|
||||
sendInit(castContext)
|
||||
|
||||
setTimeout(() => {
|
||||
ctx.$eventBus.$emit('cast-session-active', true)
|
||||
}, 500)
|
||||
setTimeout(() => {
|
||||
ctx.$eventBus.$emit('cast-session-active', true)
|
||||
}, 500)
|
||||
|
||||
break;
|
||||
case cast.framework.SessionState.SESSION_RESUMED:
|
||||
console.log('[chromecast] CAST SESSION RESUMED')
|
||||
break
|
||||
case cast.framework.SessionState.SESSION_RESUMED:
|
||||
console.log('[chromecast] CAST SESSION RESUMED')
|
||||
|
||||
setTimeout(() => {
|
||||
ctx.$eventBus.$emit('cast-session-active', true)
|
||||
}, 500)
|
||||
break;
|
||||
case cast.framework.SessionState.SESSION_ENDED:
|
||||
console.log('[chromecast] CAST SESSION DISCONNECTED')
|
||||
setTimeout(() => {
|
||||
ctx.$eventBus.$emit('cast-session-active', true)
|
||||
}, 500)
|
||||
break
|
||||
case cast.framework.SessionState.SESSION_ENDED:
|
||||
console.log('[chromecast] CAST SESSION DISCONNECTED')
|
||||
|
||||
ctx.$store.commit('globals/setCasting', false)
|
||||
ctx.$eventBus.$emit('cast-session-active', false)
|
||||
break;
|
||||
}
|
||||
})
|
||||
ctx.$store.commit('globals/setCasting', false)
|
||||
ctx.$eventBus.$emit('cast-session-active', false)
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
ctx.$store.commit('globals/setChromecastInitialized', true)
|
||||
|
||||
|
|
@ -77,4 +80,4 @@ export default (ctx) => {
|
|||
script.type = 'text/javascript'
|
||||
script.src = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1'
|
||||
document.head.appendChild(script)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,11 +81,9 @@ const Hotkeys = {
|
|||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Constants
|
||||
}
|
||||
export { Constants }
|
||||
export default ({ app }, inject) => {
|
||||
inject('constants', Constants)
|
||||
inject('keynames', KeyNames)
|
||||
inject('hotkeys', Hotkeys)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import Vue from "vue"
|
||||
import Toast from "vue-toastification"
|
||||
import "vue-toastification/dist/index.css"
|
||||
import Vue from 'vue'
|
||||
import Toast from 'vue-toastification'
|
||||
import 'vue-toastification/dist/index.css'
|
||||
|
||||
const options = {
|
||||
hideProgressBar: true,
|
||||
|
|
|
|||
|
|
@ -72,11 +72,11 @@ export const state = () => ({
|
|||
})
|
||||
|
||||
export const getters = {
|
||||
checkBookProviderExists: state => (providerValue) => {
|
||||
return state.providers.some(p => p.value === providerValue)
|
||||
checkBookProviderExists: (state) => (providerValue) => {
|
||||
return state.providers.some((p) => p.value === providerValue)
|
||||
},
|
||||
checkPodcastProviderExists: state => (providerValue) => {
|
||||
return state.podcastProviders.some(p => p.value === providerValue)
|
||||
checkPodcastProviderExists: (state) => (providerValue) => {
|
||||
return state.podcastProviders.some((p) => p.value === providerValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,13 +85,13 @@ export const actions = {}
|
|||
export const mutations = {
|
||||
addCustomMetadataProvider(state, provider) {
|
||||
if (provider.mediaType === 'book') {
|
||||
if (state.providers.some(p => p.value === provider.slug)) return
|
||||
if (state.providers.some((p) => p.value === provider.slug)) return
|
||||
state.providers.push({
|
||||
text: provider.name,
|
||||
value: provider.slug
|
||||
})
|
||||
} else {
|
||||
if (state.podcastProviders.some(p => p.value === provider.slug)) return
|
||||
if (state.podcastProviders.some((p) => p.value === provider.slug)) return
|
||||
state.podcastProviders.push({
|
||||
text: provider.name,
|
||||
value: provider.slug
|
||||
|
|
@ -100,9 +100,9 @@ export const mutations = {
|
|||
},
|
||||
removeCustomMetadataProvider(state, provider) {
|
||||
if (provider.mediaType === 'book') {
|
||||
state.providers = state.providers.filter(p => p.value !== provider.slug)
|
||||
state.providers = state.providers.filter((p) => p.value !== provider.slug)
|
||||
} else {
|
||||
state.podcastProviders = state.podcastProviders.filter(p => p.value !== provider.slug)
|
||||
state.podcastProviders = state.podcastProviders.filter((p) => p.value !== provider.slug)
|
||||
}
|
||||
},
|
||||
setCustomMetadataProviders(state, providers) {
|
||||
|
|
@ -123,4 +123,4 @@ export const mutations = {
|
|||
// Podcast providers not supported yet
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,21 @@
|
|||
|
||||
export const state = () => ({
|
||||
usersOnline: []
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
getIsUserOnline: state => id => {
|
||||
return state.usersOnline.find(u => u.id === id)
|
||||
getIsUserOnline: (state) => (id) => {
|
||||
return state.usersOnline.find((u) => u.id === id)
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
|
||||
}
|
||||
export const actions = {}
|
||||
|
||||
export const mutations = {
|
||||
setUsersOnline(state, usersOnline) {
|
||||
state.usersOnline = usersOnline
|
||||
},
|
||||
updateUserOnline(state, user) {
|
||||
var index = state.usersOnline.findIndex(u => u.id === user.id)
|
||||
var index = state.usersOnline.findIndex((u) => u.id === user.id)
|
||||
if (index >= 0) {
|
||||
state.usersOnline.splice(index, 1, user)
|
||||
} else {
|
||||
|
|
@ -26,6 +23,6 @@ export const mutations = {
|
|||
}
|
||||
},
|
||||
removeUserOnline(state, user) {
|
||||
state.usersOnline = state.usersOnline.filter(u => u.id !== user.id)
|
||||
state.usersOnline = state.usersOnline.filter((u) => u.id !== user.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue