master
宇天 2021-01-05 18:37:05 +08:00
parent 267f395476
commit 9113d7472d
5 changed files with 149 additions and 18 deletions

View File

@ -26,9 +26,9 @@
"version": "11.0.4", "version": "11.0.4",
"mirror": "https://npm.taobao.org/mirrors/electron/" "mirror": "https://npm.taobao.org/mirrors/electron/"
}, },
"files": ["src/**/*", "node_modules/iofs/*"], "files": ["src/**/*", "node_modules/iofs/*", "node_modules/epub/*"],
"mac": { "mac": {
"category": "public.app-category.developer-tools", "category": "public.app-category.utilities",
"target": "dmg", "target": "dmg",
"icon": "icons/app.icns", "icon": "icons/app.icns",
"darkModeSupport": false "darkModeSupport": false
@ -39,6 +39,7 @@
"electron-builder": "^22.1.0" "electron-builder": "^22.1.0"
}, },
"dependencies": { "dependencies": {
"epub": "^1.2.1",
"iofs": "^1.3.2" "iofs": "^1.3.2"
} }
} }

View File

@ -60,6 +60,16 @@ Anot({
ev.preventDefault() ev.preventDefault()
// clearTimeout(this.timer) // clearTimeout(this.timer)
this.isDragIn = false this.isDragIn = false
let files = Array.from(ev.dataTransfer.files)
.filter(it => it.type === 'application/epub+zip')
.map(it => {
let { name, path } = it
return { name, path }
})
let res = app.dispatch('parse-book', files)
console.log(res)
}) })
}, },
methods: {} methods: {}

View File

@ -8,6 +8,7 @@ const { app, BrowserWindow, protocol, ipcMain } = require('electron')
const path = require('path') const path = require('path')
const fs = require('iofs') const fs = require('iofs')
require('./tools/init')
const { createMainWindow, createFloatWindow } = require('./tools/window') const { createMainWindow, createFloatWindow } = require('./tools/window')
const createMenu = require('./tools/menu') const createMenu = require('./tools/menu')
const Socket = require('./tools/socket') const Socket = require('./tools/socket')
@ -17,14 +18,18 @@ const MIME_TYPES = {
'.html': 'text/html', '.html': 'text/html',
'.htm': 'text/plain', '.htm': 'text/plain',
'.css': 'text/css', '.css': 'text/css',
'.jpg': 'image/jpg', '.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.png': 'image/png', '.png': 'image/png',
'.gif': 'image/gif', '.gif': 'image/gif',
'.svg': 'image/svg+xml', '.svg': 'image/svg+xml',
'.ico': 'image/ico' '.ico': 'image/ico',
all: 'text/*'
} }
const ROOT = __dirname const ROOT = __dirname
const HOME = path.resolve(app.getPath('userData'))
const CACHE_DIR = path.join(HOME, 'book_cache')
var timer var timer
@ -33,7 +38,8 @@ app.commandLine.appendSwitch('--lang', 'zh-CN')
app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required') app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required')
protocol.registerSchemesAsPrivileged([ protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } } { scheme: 'app', privileges: { secure: true, standard: true } },
{ scheme: 'book', privileges: { secure: true, standard: true } }
]) ])
/* ----------------------------------------------------- */ /* ----------------------------------------------------- */
@ -43,16 +49,39 @@ app.dock.hide()
// 初始化应用 // 初始化应用
app.once('ready', () => { app.once('ready', () => {
// 注册协议 // 注册协议
protocol.registerBufferProtocol('app', (req, cb) => { protocol.registerStreamProtocol('app', function(req, cb) {
let file = req.url.replace(/^app:\/\/local\//, '') var file = decodeURIComponent(req.url.replace(/^app:\/\/local\//, ''))
let ext = path.extname(req.url) var ext = path.extname(file)
let buff = fs.cat(path.resolve(ROOT, file))
cb({ data: buff, mimeType: MIME_TYPES[ext] }) file = path.resolve(ROOT, file)
cb({
data: fs.origin.createReadStream(file),
mimeType: MIME_TYPES[ext],
headers: {
'Cache-Control': 'max-age=144000000'
}
})
})
protocol.registerStreamProtocol('book', function(req, cb) {
var file = decodeURIComponent(req.url.replace(/^book:[\/]+/, '/'))
var ext = path.extname(file)
file = path.resolve(CACHE_DIR, file)
cb({
data: fs.origin.createReadStream(file),
mimeType: MIME_TYPES[ext] || MIME_TYPES.all,
headers: {
'Cache-Control': 'max-age=144000000'
}
})
}) })
// 创建浏览器窗口 // 创建浏览器窗口
app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png')) app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png'))
app.__float__ = createFloatWindow() // app.__float__ = createFloatWindow()
createMenu(app.__main__) createMenu(app.__main__)
Socket(app) Socket(app)
@ -63,10 +92,10 @@ app.once('ready', () => {
app.exit() app.exit()
}) })
// mac专属事件,点击dock栏图标,可激活窗口 // mac专属事件, 点击dock栏图标, 可激活窗口
// app.on('activate', _ => { app.on('activate', _ => {
// if (app.__main__) { if (app.__main__) {
// app.__main__.restore() app.__main__.restore()
// } }
// }) })
}) })

32
src/tools/init.js Normal file
View File

@ -0,0 +1,32 @@
/**
* 初始化
* @author yutent<yutent.io@gmail.com>
* @date 2021/01/05 10:02:02
*/
const { app } = require('electron')
const path = require('path')
const fs = require('iofs')
const HOME = path.resolve(app.getPath('userData'))
/* ********** 修复环境变量 start *********** */
let PATH_SET = new Set()
process.env.PATH.split(':').forEach(_ => {
PATH_SET.add(_)
})
PATH_SET.add('/usr/local/bin')
PATH_SET.add('/usr/local/sbin')
process.env.PATH = Array.from(PATH_SET).join(':')
PATH_SET = null
/* ********** 修复环境变量 end *********** */
const INIT_FILE = path.join(HOME, 'app.cache')
const CACHE_DIR = path.join(HOME, 'book_cache')
if (!fs.exists(INIT_FILE)) {
fs.echo('[]', INIT_FILE)
fs.mkdir(CACHE_DIR)
}

View File

@ -4,7 +4,13 @@
* @date 2021/01/04 14:58:46 * @date 2021/01/04 14:58:46
*/ */
const { ipcMain, net } = require('electron') const { app, ipcMain, net } = require('electron')
const fs = require('iofs')
const path = require('path')
const Epub = require('epub')
const HOME = path.resolve(app.getPath('userData'))
const CACHE_DIR = path.join(HOME, 'book_cache')
function fetch(url) { function fetch(url) {
return new Promise((y, n) => { return new Promise((y, n) => {
@ -39,6 +45,59 @@ module.exports = function(app) {
break break
case 'parse-book': case 'parse-book':
let books = conn.data
let eb = new Epub(books[0].path)
function saveImage(id, name) {
return new Promise(done => {
eb.getImage(id, (err, buf) => {
fs.echo(buf, path.resolve(CACHE_DIR, name))
done()
})
})
}
function saveHtml(id, name) {
return new Promise(done => {
eb.getChapter(id, (err, txt) => {
txt = (txt + '').replace(/<([\w\-]+)[^>]*?>/g, '<$1>')
fs.echo(txt, path.resolve(CACHE_DIR, name))
done()
})
})
}
eb.on('end', async _ => {
loop: for (let k in eb.manifest) {
let it = eb.manifest[k]
switch (it['media-type']) {
case 'text/css':
continue loop
break
case 'application/x-dtbncx+xml':
fs.echo(
JSON.stringify(eb.toc),
path.resolve(CACHE_DIR, it.href)
)
break
case 'application/xhtml+xml':
await saveHtml(it.id, it.href)
break
default:
if (it['media-type'].startsWith('image')) {
saveImage(it.id, it.href)
}
break
}
}
ev.returnValue = [eb.manifest, eb.flow]
})
eb.parse()
break break
} }
}) })