2016-08-23 02:28:30 +12:00
|
|
|
/* global chrome */
|
|
|
|
'use strict'
|
2016-06-20 08:28:28 +12:00
|
|
|
|
2016-06-28 09:19:01 +12:00
|
|
|
import FimFic2Epub from './FimFic2Epub'
|
2016-08-23 02:28:30 +12:00
|
|
|
import m from 'mithril'
|
2016-08-15 21:11:20 +12:00
|
|
|
import { saveAs } from 'file-saver'
|
|
|
|
|
2016-08-24 08:04:38 +12:00
|
|
|
function blobToDataURL (blob) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
let fr = new FileReader()
|
|
|
|
fr.onloadend = function (e) { resolve(fr.result) }
|
|
|
|
fr.readAsDataURL(blob)
|
|
|
|
})
|
2016-08-24 02:32:55 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
function blobToArrayBuffer (blob) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
let fr = new FileReader()
|
|
|
|
fr.onloadend = function (e) { resolve(fr.result) }
|
|
|
|
fr.readAsArrayBuffer(blob)
|
|
|
|
})
|
2016-08-15 21:11:20 +12:00
|
|
|
}
|
2016-06-20 08:28:28 +12:00
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
const isChromeExt = typeof chrome !== 'undefined'
|
|
|
|
|
2016-06-21 09:04:08 +12:00
|
|
|
const STORY_ID = document.location.pathname.match(/^\/story\/(\d*)/)[1]
|
2016-06-20 08:28:28 +12:00
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
let ffc
|
2016-06-20 08:28:28 +12:00
|
|
|
|
2016-06-28 09:19:01 +12:00
|
|
|
const epubButton = document.querySelector('.story_container ul.chapters li.bottom a[title="Download Story (.epub)"]')
|
2016-06-21 09:04:08 +12:00
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
const dialogContainer = document.createElement('div')
|
|
|
|
dialogContainer.id = 'epubDialogContainer'
|
|
|
|
document.body.appendChild(dialogContainer)
|
|
|
|
|
|
|
|
let checkbox = {
|
|
|
|
view: function (ctrl, args, text) {
|
2016-08-24 08:04:38 +12:00
|
|
|
return m('label.toggleable-switch', {style: 'white-space: nowrap;'}, [
|
|
|
|
m('input', {type: 'checkbox', name: args.name, checked: args.checked, onchange: args.onchange}),
|
|
|
|
m('a', {style: 'margin-right: 10px'}),
|
2016-08-23 02:28:30 +12:00
|
|
|
text
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-24 02:32:55 +12:00
|
|
|
let ffcProgress = m.prop(-1)
|
|
|
|
let ffcStatus = m.prop('')
|
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
let dialog = {
|
|
|
|
controller (args) {
|
2016-08-24 08:04:38 +12:00
|
|
|
this.isLoading = m.prop(true)
|
2016-08-23 02:28:30 +12:00
|
|
|
this.dragging = m.prop(false)
|
2016-08-23 07:57:19 +12:00
|
|
|
this.xpos = m.prop(0)
|
|
|
|
this.ypos = m.prop(0)
|
2016-08-23 02:28:30 +12:00
|
|
|
this.el = m.prop(null)
|
2016-08-24 02:32:55 +12:00
|
|
|
this.coverFile = m.prop(null)
|
2016-08-24 08:04:38 +12:00
|
|
|
this.coverUrl = m.prop('')
|
|
|
|
this.checkboxCoverUrl = m.prop(false)
|
|
|
|
this.subjects = m.prop(ffc.subjects)
|
2016-08-24 02:32:55 +12:00
|
|
|
|
|
|
|
this.setCoverFile = (e) => {
|
|
|
|
this.coverFile(e.target.files ? e.target.files[0] : null)
|
|
|
|
}
|
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
this.ondown = (e) => {
|
2016-08-23 07:57:19 +12:00
|
|
|
let rect = this.el().firstChild.getBoundingClientRect()
|
|
|
|
let offset = {x: e.pageX - rect.left - document.body.scrollLeft, y: e.pageY - rect.top - document.body.scrollTop}
|
2016-08-23 02:28:30 +12:00
|
|
|
this.dragging(true)
|
|
|
|
let onmove = (e) => {
|
|
|
|
e.preventDefault()
|
|
|
|
if (this.dragging()) {
|
2016-08-23 07:57:19 +12:00
|
|
|
this.xpos(Math.max(0, e.pageX - offset.x))
|
|
|
|
this.ypos(Math.max(0, e.pageY - offset.y))
|
|
|
|
this.move()
|
2016-08-15 21:11:20 +12:00
|
|
|
}
|
2016-08-23 02:28:30 +12:00
|
|
|
}
|
|
|
|
let onup = () => {
|
|
|
|
this.dragging(false)
|
|
|
|
window.removeEventListener('mousemove', onmove)
|
|
|
|
window.removeEventListener('mouseup', onup)
|
|
|
|
}
|
|
|
|
window.addEventListener('mousemove', onmove, false)
|
|
|
|
window.addEventListener('mouseup', onup, false)
|
|
|
|
}
|
2016-08-24 08:04:38 +12:00
|
|
|
this.onOpen = function (el, isInitialized) {
|
|
|
|
if (!isInitialized) {
|
2016-08-23 07:57:19 +12:00
|
|
|
this.el(el)
|
2016-08-24 08:04:38 +12:00
|
|
|
this.center()
|
|
|
|
this.isLoading(true)
|
|
|
|
ffc.fetchMetadata().then(() => {
|
|
|
|
this.isLoading(false)
|
|
|
|
m.redraw(true)
|
|
|
|
this.center()
|
|
|
|
})
|
2016-08-23 07:57:19 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
this.move = () => {
|
|
|
|
this.el().style.left = this.xpos() + 'px'
|
|
|
|
this.el().style.top = this.ypos() + 'px'
|
|
|
|
}
|
2016-08-24 08:04:38 +12:00
|
|
|
this.center = () => {
|
|
|
|
let rect = this.el().firstChild.getBoundingClientRect()
|
|
|
|
this.xpos((window.innerWidth / 2) - (rect.width / 2) + document.body.scrollLeft)
|
|
|
|
this.ypos((window.innerHeight / 2) - (rect.height / 2) + document.body.scrollTop)
|
|
|
|
this.move()
|
|
|
|
}
|
|
|
|
|
2016-08-23 07:57:19 +12:00
|
|
|
this.createEpub = (e) => {
|
2016-08-24 02:32:55 +12:00
|
|
|
ffcProgress(0)
|
|
|
|
ffcStatus('')
|
2016-08-23 07:57:19 +12:00
|
|
|
e.target.disabled = true
|
2016-08-24 02:32:55 +12:00
|
|
|
let chain = Promise.resolve()
|
2016-08-24 08:04:38 +12:00
|
|
|
ffc.coverUrl = ''
|
|
|
|
ffc.coverImage = null
|
|
|
|
if (this.checkboxCoverUrl()) {
|
|
|
|
ffc.coverUrl = this.coverUrl()
|
|
|
|
} else if (this.coverFile()) {
|
|
|
|
chain = chain.then(blobToArrayBuffer.bind(null, this.coverFile())).then(ffc.setCoverImage.bind(ffc))
|
2016-08-24 02:32:55 +12:00
|
|
|
}
|
|
|
|
m.redraw()
|
|
|
|
|
|
|
|
chain
|
|
|
|
.then(ffc.fetch.bind(ffc))
|
2016-08-23 07:57:19 +12:00
|
|
|
.then(ffc.build.bind(ffc))
|
|
|
|
.then(ffc.getFile.bind(ffc)).then((file) => {
|
|
|
|
console.log('Saving file...')
|
|
|
|
if (typeof safari !== 'undefined') {
|
2016-08-24 08:04:38 +12:00
|
|
|
blobToDataURL(file).then((dataurl) => {
|
2016-08-23 07:57:19 +12:00
|
|
|
document.location.href = dataurl
|
|
|
|
alert('Add .epub to the filename of the downloaded file')
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
saveAs(file, ffc.filename)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2016-08-23 02:28:30 +12:00
|
|
|
},
|
2016-08-24 02:32:55 +12:00
|
|
|
|
2016-08-23 02:28:30 +12:00
|
|
|
view (ctrl, args, extras) {
|
2016-08-23 07:57:19 +12:00
|
|
|
return m('.drop-down-pop-up-container', {config: ctrl.onOpen.bind(ctrl)}, m('.drop-down-pop-up', [
|
|
|
|
m('h1', {onmousedown: ctrl.ondown}, m('i.fa.fa-book'), 'Export to EPUB', m('a.close_button', {onclick: closeDialog})),
|
2016-08-24 08:04:38 +12:00
|
|
|
ctrl.isLoading() ? m('div', {style: 'text-align:center;'}, m('i.fa.fa-spin.fa-spinner', {style: 'font-size:50px; margin:20px; color:#777;'})) : m('.drop-down-pop-up-content', [
|
2016-08-23 07:57:19 +12:00
|
|
|
m('table.properties', [
|
2016-08-24 02:32:55 +12:00
|
|
|
m('tr', m('td.label', 'Custom cover image'), m('td',
|
2016-08-24 08:04:38 +12:00
|
|
|
ctrl.checkboxCoverUrl() ? m('input', {type: 'url', placeholder: 'Image URL', onchange: m.withAttr('value', ctrl.coverUrl)}) : m('input', {type: 'file', accept: 'image/*', onchange: ctrl.setCoverFile})
|
|
|
|
), m('td', m(checkbox, {checked: ctrl.checkboxCoverUrl(), onchange: m.withAttr('checked', ctrl.checkboxCoverUrl)}, 'Use image URL'))),
|
|
|
|
m('tr', m('td.section_header', {colspan: 3}, m('b', 'Metadata'))),
|
|
|
|
m('tr', m('td.label', 'Categories'), m('td', {colspan: 2},
|
|
|
|
m('textarea', {rows: 5}, ctrl.subjects().join('\n')),
|
|
|
|
m(checkbox, {checked: false}, 'Join categories into one (for iBooks)')
|
2016-08-24 02:32:55 +12:00
|
|
|
))
|
|
|
|
// m('tr', m('td.label', 'Chapter headings'), m('td', m(checkbox, {checked: true})))
|
2016-08-23 07:57:19 +12:00
|
|
|
]),
|
|
|
|
m('.drop-down-pop-up-footer', [
|
2016-08-24 02:32:55 +12:00
|
|
|
m('button.styled_button', {onclick: ctrl.createEpub, disabled: ffcProgress() >= 0 && ffcProgress() < 1}, 'Create EPUB'),
|
2016-08-24 08:04:38 +12:00
|
|
|
m('.rating_container',
|
|
|
|
m('.bars_container', m('.bar_container', m('.bar_dislike', m('.bar.bar_like', {style: {width: Math.max(0, ffcProgress()) * 100 + '%'}})))),
|
2016-08-24 02:32:55 +12:00
|
|
|
' ',
|
2016-08-24 08:04:38 +12:00
|
|
|
ffcProgress() >= 0 && ffcProgress() < 1 ? m('i.fa.fa-spin.fa-spinner') : null,
|
2016-08-24 02:32:55 +12:00
|
|
|
' ',
|
|
|
|
ffcStatus()
|
2016-08-24 08:04:38 +12:00
|
|
|
)
|
2016-08-23 07:57:19 +12:00
|
|
|
])
|
2016-08-23 02:28:30 +12:00
|
|
|
])
|
|
|
|
]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function openDialog (args, extras) {
|
|
|
|
m.mount(dialogContainer, m(dialog, args, extras))
|
|
|
|
}
|
|
|
|
function closeDialog () {
|
|
|
|
m.mount(dialogContainer, null)
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickButton () {
|
|
|
|
if (!STORY_ID) return
|
|
|
|
if (!ffc) ffc = new FimFic2Epub(STORY_ID)
|
2016-08-24 02:32:55 +12:00
|
|
|
ffc.on('progress', (percent, status) => {
|
|
|
|
ffcProgress(percent)
|
|
|
|
if (status) {
|
|
|
|
ffcStatus(status)
|
|
|
|
}
|
|
|
|
m.redraw()
|
|
|
|
})
|
2016-08-23 02:28:30 +12:00
|
|
|
|
|
|
|
openDialog()
|
|
|
|
}
|
|
|
|
|
|
|
|
if (epubButton) {
|
|
|
|
if (isChromeExt) {
|
|
|
|
chrome.runtime.sendMessage({showPageAction: true})
|
|
|
|
chrome.runtime.onMessage.addListener(function (request) {
|
|
|
|
if (request === 'pageAction') {
|
|
|
|
clickButton()
|
|
|
|
}
|
2016-06-28 19:39:31 +12:00
|
|
|
})
|
2016-08-23 02:28:30 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
epubButton.addEventListener('click', function (e) {
|
|
|
|
e.preventDefault()
|
|
|
|
clickButton()
|
2016-06-21 18:39:26 +12:00
|
|
|
}, false)
|
2016-06-21 09:04:08 +12:00
|
|
|
}
|