一大波优化
parent
b42d7ae19a
commit
4bcc894ec3
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "sonist",
|
||||
"version": "0.9.4",
|
||||
"version": "0.9.5",
|
||||
"description": "Music Player",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
|
@ -29,11 +29,7 @@
|
|||
"buildResources": "icons",
|
||||
"output": "build"
|
||||
},
|
||||
"files": [
|
||||
"src/**/*",
|
||||
"node_modules/iofs/*",
|
||||
"node_modules/crypto.js/*"
|
||||
],
|
||||
"files": ["src/**/*", "node_modules/iofs/*", "node_modules/crypto.js/*"],
|
||||
"mac": {
|
||||
"category": "public.app-category.music",
|
||||
"target": "dmg",
|
||||
|
|
|
@ -20,24 +20,18 @@ import Search from '/js/modules/search.js'
|
|||
import KTV from '/js/modules/ktv.js'
|
||||
import PLAYCTRL from '/js/modules/play-ctrl.js'
|
||||
|
||||
import {
|
||||
createDesktopLrcWindow,
|
||||
createMiniWindow
|
||||
} from '/js/modules/extra-win.js'
|
||||
|
||||
const log = console.log
|
||||
|
||||
const fs = require('iofs')
|
||||
const path = require('path')
|
||||
|
||||
const { remote } = require('electron')
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
|
||||
const { createDesktopLrcWindow, createMiniWindow } = remote.app.windows
|
||||
|
||||
const WIN = remote.getCurrentWindow()
|
||||
const MAIN_SCREEN = remote.screen.getPrimaryDisplay()
|
||||
|
||||
const HOME_PATH = remote.app.getPath('appData')
|
||||
const APP_INI_PATH = path.join(HOME_PATH, 'app.ini')
|
||||
const LYRICS_PATH = path.join(HOME_PATH, 'lyrics')
|
||||
const PLAY_MODE = {
|
||||
0: 'all',
|
||||
1: 'single',
|
||||
|
@ -51,22 +45,20 @@ window.TS = store.collection('temp')
|
|||
window.SONIST = new AudioPlayer()
|
||||
window.LYRICS = new Lyrics()
|
||||
|
||||
let appInit = fs.cat(APP_INI_PATH)
|
||||
let appInit = ipcRenderer.sendSync('get-init')
|
||||
|
||||
Anot.ss('app-init', appInit + '')
|
||||
|
||||
appInit = JSON.parse(appInit)
|
||||
Anot.ss('app-init', appInit)
|
||||
|
||||
const LRC_WIN = createDesktopLrcWindow(MAIN_SCREEN)
|
||||
const MINI_WIN = createMiniWindow(MAIN_SCREEN, WIN)
|
||||
// const MINI_WIN = createMiniWindow(MAIN_SCREEN, WIN)
|
||||
|
||||
WIN.hide()
|
||||
MINI_WIN.show()
|
||||
// WIN.hide()
|
||||
// MINI_WIN.show()
|
||||
|
||||
MINI_WIN.opener = WIN
|
||||
MINI_WIN.openDevTools()
|
||||
// MINI_WIN.opener = WIN
|
||||
// MINI_WIN.openDevTools()
|
||||
|
||||
window.MINI_WIN = MINI_WIN
|
||||
// window.MINI_WIN = MINI_WIN
|
||||
Anot({
|
||||
$id: 'app',
|
||||
state: {
|
||||
|
@ -330,7 +322,7 @@ Anot({
|
|||
this.updateCurr(song)
|
||||
this.isPlaying = true
|
||||
this.draw(true)
|
||||
LYRICS.__init__(song.lyrics)
|
||||
LYRICS.__init__(song.id)
|
||||
} else {
|
||||
if (SONIST.stat === 'ready') {
|
||||
let played = this.isPlaying
|
||||
|
@ -351,7 +343,7 @@ Anot({
|
|||
this.draw(true)
|
||||
// this.ktvMode = 1
|
||||
|
||||
LYRICS.__init__(it.lyrics)
|
||||
LYRICS.__init__(it.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* 额外的小窗口
|
||||
* @author yutent<yutent@doui.cc>
|
||||
* @date 2019/01/21 21:24:04
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const {
|
||||
remote: { BrowserWindow }
|
||||
} = require('electron')
|
||||
|
||||
export const createDesktopLrcWindow = function(screen) {
|
||||
let win = new BrowserWindow({
|
||||
title: '',
|
||||
width: 1024,
|
||||
height: 100,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
alwaysOnTop: true,
|
||||
x: (screen.size.width - 1024) / 2,
|
||||
y: screen.size.height - 100,
|
||||
skipTaskbar: true,
|
||||
hasShadow: false,
|
||||
thickFrame: false,
|
||||
transparent: true,
|
||||
show: false
|
||||
})
|
||||
|
||||
// win.loadURL('http://127.0.0.1:10240/desktop-lrc.html')
|
||||
win.loadURL('app://local/desktop-lrc.html')
|
||||
return win
|
||||
}
|
||||
|
||||
export const createMiniWindow = function(screen, pwin) {
|
||||
let win = new BrowserWindow({
|
||||
title: '',
|
||||
width: 320,
|
||||
height: 60,
|
||||
frame: false,
|
||||
// parent: pwin,
|
||||
resizable: false,
|
||||
alwaysOnTop: true,
|
||||
x: screen.size.width - 320,
|
||||
y: 0,
|
||||
skipTaskbar: true,
|
||||
show: false
|
||||
})
|
||||
|
||||
// win.loadURL('http://127.0.0.1:10240/mini-win.html')
|
||||
win.loadURL('app://local/mini-win.html')
|
||||
return win
|
||||
}
|
|
@ -9,13 +9,7 @@
|
|||
import Api from '/js/api.js'
|
||||
import Local from '/js/modules/local.js'
|
||||
|
||||
const fs = require('iofs')
|
||||
const path = require('path')
|
||||
const { app } = require('electron').remote
|
||||
|
||||
const HOME_PATH = app.getPath('appData')
|
||||
const MUSIC_DB_PATH = path.join(HOME_PATH, 'music.db')
|
||||
const LYRICS_PATH = path.join(HOME_PATH, 'lyrics')
|
||||
const { ipcRenderer } = require('electron')
|
||||
const log = console.log
|
||||
|
||||
export default {
|
||||
|
@ -85,9 +79,8 @@ export default {
|
|||
song.albumId = json.album_id
|
||||
song.kgHash = json.hash
|
||||
song.cover = json.img
|
||||
song.lyrics = path.join(LYRICS_PATH, `${song.id}.lrc`)
|
||||
|
||||
LS.insert(song)
|
||||
LS.update(id, song)
|
||||
Local.list.set(SONIST.__CURR__, song)
|
||||
|
||||
SONIST.clear()
|
||||
|
@ -96,10 +89,10 @@ export default {
|
|||
this.updateCurr(song)
|
||||
this.draw(true)
|
||||
|
||||
fs.echo(json.lyrics, song.lyrics)
|
||||
fs.echo(JSON.stringify(LS.getAll(), '', 2), MUSIC_DB_PATH)
|
||||
ipcRenderer.send('save-lrc', { id, lrc: json.lyrics })
|
||||
ipcRenderer.send('set-music', LS.getAll())
|
||||
|
||||
LYRICS.__init__(song.lyrics)
|
||||
LYRICS.__init__(id)
|
||||
|
||||
layer.toast('歌词应用成功...')
|
||||
|
||||
|
|
|
@ -9,21 +9,14 @@
|
|||
import Api from '/js/api.js'
|
||||
import { ID3 } from '/lib/audio/index.js'
|
||||
|
||||
const fs = require('iofs')
|
||||
const path = require('path')
|
||||
const crypto = require('crypto.js')
|
||||
const { app, dialog } = require('electron').remote
|
||||
const { remote, ipcRenderer } = require('electron')
|
||||
|
||||
const log = console.log
|
||||
const HOME_PATH = app.getPath('appData')
|
||||
const MUSIC_DB_PATH = path.join(HOME_PATH, 'music.db')
|
||||
const LYRICS_PATH = path.join(HOME_PATH, 'lyrics')
|
||||
|
||||
const SUPPORTED_EXTS = ['.mp3', '.webm', '.ogg', '.flac', '.m4a', '.aac']
|
||||
|
||||
let appInit = {}
|
||||
let dbCache = fs.cat(MUSIC_DB_PATH)
|
||||
dbCache = JSON.parse(dbCache)
|
||||
let dbCache = []
|
||||
|
||||
export default Anot({
|
||||
$id: 'local',
|
||||
|
@ -40,8 +33,10 @@ export default Anot({
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
LS.insert(dbCache)
|
||||
appInit = JSON.parse(Anot.ss('app-init'))
|
||||
dbCache = ipcRenderer.sendSync('get-music')
|
||||
|
||||
LS.insert(dbCache)
|
||||
|
||||
dbCache = null
|
||||
this.__APP__ = Anot.vmodels.app
|
||||
|
@ -78,12 +73,6 @@ export default Anot({
|
|||
if (!it.cover) {
|
||||
if (idx === undefined) {
|
||||
idx = SONIST.__CURR__
|
||||
// for (let i in this.list.$model) {
|
||||
// if (this.list[i].id === it.id) {
|
||||
// idx = i
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
}
|
||||
let _P = Promise.resolve(true)
|
||||
if (!it.kgHash) {
|
||||
|
@ -105,7 +94,6 @@ export default Anot({
|
|||
it.albumId = json.album_id
|
||||
it.kgHash = json.hash
|
||||
it.cover = json.img
|
||||
it.lyrics = path.join(LYRICS_PATH, `${it.id}.lrc`)
|
||||
|
||||
LS.insert(it)
|
||||
this.list.set(idx, it)
|
||||
|
@ -116,10 +104,13 @@ export default Anot({
|
|||
this.__APP__.updateCurr(it)
|
||||
this.__APP__.draw(true)
|
||||
|
||||
fs.echo(json.lyrics, it.lyrics)
|
||||
fs.echo(JSON.stringify(LS.getAll(), '', 2), MUSIC_DB_PATH)
|
||||
ipcRenderer.send('save-lrc', {
|
||||
id: it.id,
|
||||
lrc: json.lyrics
|
||||
})
|
||||
ipcRenderer.send('set-music', LS.getAll())
|
||||
|
||||
LYRICS.__init__(it.lyrics)
|
||||
LYRICS.__init__(it.id)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -144,7 +135,7 @@ export default Anot({
|
|||
SONIST.clear()
|
||||
SONIST.push(dbCache)
|
||||
|
||||
fs.echo(JSON.stringify(dbCache, '', 2), MUSIC_DB_PATH)
|
||||
ipcRenderer.send('set-music', dbCache)
|
||||
dbCache = null
|
||||
|
||||
layer.toast(`刷新缓存完成,新增${this.__NEW_NUM__}首`)
|
||||
|
@ -160,6 +151,7 @@ export default Anot({
|
|||
let item = LS.get(hash)
|
||||
if (item) {
|
||||
item.path = `file://${song}`
|
||||
delete item.lyrics
|
||||
LS.update(hash, item)
|
||||
return this.__checkSong__(el)
|
||||
}
|
||||
|
@ -182,22 +174,12 @@ export default Anot({
|
|||
return
|
||||
}
|
||||
if (appInit.musicPath) {
|
||||
if (fs.isdir(appInit.musicPath)) {
|
||||
this.__LIST__ = ipcRenderer.sendSync('scan-dir', appInit.musicPath)
|
||||
if (this.__LIST__) {
|
||||
this.__APP__.loading = true
|
||||
|
||||
this.__LIST__ = fs.ls(appInit.musicPath, true).filter(_ => {
|
||||
if (fs.isdir(_)) {
|
||||
return false
|
||||
} else {
|
||||
let { ext, name } = path.parse(_)
|
||||
if (!ext || name.startsWith('.')) {
|
||||
return false
|
||||
}
|
||||
return SUPPORTED_EXTS.includes(ext)
|
||||
}
|
||||
})
|
||||
this.__WAIT_FOR_SCAN__ = this.__LIST__.length
|
||||
this.__NEW_NUM__ = 0
|
||||
|
||||
ev.target.textContent = '正在扫描, 请稍候...'
|
||||
this.__checkSong__(ev.target)
|
||||
} else {
|
||||
|
@ -238,7 +220,7 @@ export default Anot({
|
|||
SONIST.clear()
|
||||
SONIST.push(LS.getAll())
|
||||
|
||||
fs.echo(JSON.stringify(LS.getAll(), '', 2), MUSIC_DB_PATH)
|
||||
ipcRenderer.send('set-music', LS.getAll())
|
||||
},
|
||||
handleMenu(it, idx, ev) {
|
||||
let that = this
|
||||
|
@ -281,7 +263,7 @@ export default Anot({
|
|||
SONIST.clear()
|
||||
SONIST.push(LS.getAll())
|
||||
|
||||
fs.echo(JSON.stringify(LS.getAll(), '', 2), MUSIC_DB_PATH)
|
||||
ipcRenderer.send('set-music', LS.getAll())
|
||||
}
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -8,17 +8,14 @@
|
|||
|
||||
import '/lib/form/index.js'
|
||||
|
||||
const fs = require('iofs')
|
||||
const path = require('path')
|
||||
const { app, dialog } = require('electron').remote
|
||||
const {
|
||||
remote: { app, dialog },
|
||||
ipcRenderer
|
||||
} = require('electron')
|
||||
|
||||
const log = console.log
|
||||
|
||||
const HOME_PATH = app.getPath('appData')
|
||||
const APP_INI_PATH = path.join(HOME_PATH, 'app.ini')
|
||||
|
||||
let appInit = fs.cat(APP_INI_PATH)
|
||||
|
||||
appInit = JSON.parse(appInit)
|
||||
let appInit = ipcRenderer.sendSync('get-init')
|
||||
|
||||
export default Anot({
|
||||
$id: 'profile',
|
||||
|
@ -58,9 +55,9 @@ export default Anot({
|
|||
|
||||
Object.assign(appInit, setting)
|
||||
|
||||
let cache = JSON.stringify(appInit, '', 2)
|
||||
fs.echo(cache, APP_INI_PATH)
|
||||
Anot.ss('app-init', cache)
|
||||
ipcRenderer.send('set-init', appInit)
|
||||
|
||||
Anot.ss('app-init', appInit)
|
||||
|
||||
layer.toast('保存成功')
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -7,13 +7,13 @@
|
|||
'use strict'
|
||||
|
||||
const log = console.log
|
||||
const fs = require('iofs')
|
||||
const { EventEmitter } = require('events')
|
||||
const util = require('util')
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
class Lyrics {
|
||||
// 歌词初始化
|
||||
__init__(lrcFile) {
|
||||
__init__(id) {
|
||||
this.lib = []
|
||||
this.curr = []
|
||||
this.lrc = {
|
||||
|
@ -21,21 +21,16 @@ class Lyrics {
|
|||
r: { bg: '', txt: '' }
|
||||
}
|
||||
|
||||
if (!lrcFile || !fs.exists(lrcFile)) {
|
||||
log('no lrc file', lrcFile)
|
||||
let lrc = ipcRenderer.sendSync('read-lrc', id)
|
||||
if (!id || lrc === null) {
|
||||
log('no lrc file', id)
|
||||
return false
|
||||
}
|
||||
|
||||
this.__LRC__ = lrcFile
|
||||
|
||||
// log(this.__LRC__)
|
||||
|
||||
let lrc = fs
|
||||
.cat(lrcFile)
|
||||
.toString('utf8')
|
||||
.split('\n')
|
||||
this.__ID__ = id
|
||||
|
||||
this.lib = lrc
|
||||
.split('\n')
|
||||
.map(it => {
|
||||
if (it) {
|
||||
let matches = it.match(/^\[([0-9\.\:]+)\](.+)/)
|
||||
|
@ -85,7 +80,7 @@ class Lyrics {
|
|||
|
||||
// 歌词向前调整指定时间
|
||||
forward(time = 0) {
|
||||
if (!this.__LRC__) {
|
||||
if (!this.__ID__) {
|
||||
return
|
||||
}
|
||||
clearTimeout(this.__TIMER__)
|
||||
|
@ -109,7 +104,7 @@ class Lyrics {
|
|||
|
||||
// 延时3秒写入
|
||||
this.__TIMER__ = setTimeout(() => {
|
||||
fs.echo(lrc, this.__LRC__)
|
||||
ipcRenderer.sendSync('save-lrc', { id: this.__ID__, lrc })
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
const __STORE__={};function parse$And(_){let t="";for(let e in _){let i=_[e];switch(Anot.type(i)){case"object":if(i.$has){t+=`it.${e}.indexOf(${JSON.stringify(i.$has)}) > -1`;break}if(i.$in){t+=`${JSON.stringify(i.$in)}.indexOf(it.${e}) > -1`;break}if(i.$regex){t+=`${i.$regex}.test(it.${e})`;break}if(i.$lt||i.$lte){t+=`it.${e} <${i.$lte?"=":""} ${i.$lt||i.$lte}`,(i.$gt||i.$gte)&&(t+=` && it.${e} >${i.$gte?"=":""} ${i.$gt||i.$gte}`);break}if(i.$gt||i.$gte){t+=`it.${e} >${i.$gte?"=":""} ${i.$gt||i.$gte}`;break}if(i.$eq){t+=`it.${e} === ${i.$eq}`;break}default:t+=`it.${e} === ${JSON.stringify(_[e])}`}t+=" && "}return(t=t.slice(0,-4))||(t="true"),t}function parse$Or(_){let t="";return _.forEach(_=>{t+="(",t+=parse$And(_),t+=") || "}),t.slice(0,-4)}class AnotStore{constructor(_){Anot.hideProperty(this,"__name__",_),Anot.hideProperty(this,"__LAST_QUERY__",""),Anot.hideProperty(this,"__QUERY_HISTORY__",[]),__STORE__[_]||(__STORE__[_]=[],__STORE__[`${_}Dict`]={})}static collection(_){return new this(_)}__MAKE_FN__(_){let t="\n let result = [];\n let num = 0;\n for (let it of arr) {\n if(";return _.$or?t+=parse$Or(_.$or):t+=parse$And(_),t+="){\n result.push(it)\n num++\n if(limit > 0 && num >= limit){\n break\n }\n }\n }\n return result;",Function("arr","limit",t)}clear(_){this.__QUERY_HISTORY__=[],this.__LAST_QUERY__="",_&&(__STORE__[this.__name__]=[],__STORE__[`${this.__name__}Dict`]={})}getAll({filter:_,limit:t=[]}={}){const e=__STORE__[this.__name__];let i=[],r=!1;if(!e||!e.length)return i;if(t.length<1&&(t=[0]),t.length<2&&_&&(r=!0,t[0]>0&&t.unshift(0)),_){let n=JSON.stringify(_);if(this.__LAST_QUERY__===n)i=this.__QUERY_HISTORY__.slice.apply(this.__QUERY_HISTORY__,t);else{i=this.__MAKE_FN__(_)(e,r&&t[1]||0),r||(this.__LAST_QUERY__=n,this.__QUERY_HISTORY__=i,i=this.__QUERY_HISTORY__.slice.apply(this.__QUERY_HISTORY__,t))}}else i=e.slice.apply(e,t);return Anot.deepCopy(i)}get(_){const t=__STORE__[`${this.__name__}Dict`];return Anot.deepCopy(t[_])||null}count({filter:_}={}){return _?this.__LAST_QUERY__===JSON.stringify(_)?this.__QUERY_HISTORY__.length:this.getAll({filter:_,limit:[0]}).length:__STORE__[this.__name__].length}__INSERT__(_,t){let e=__STORE__[this.__name__],i=__STORE__[`${this.__name__}Dict`],r=_[t||"id"];i[r]?this.update(r,_):(e.push(_),i[r]=_)}insert(_,t){Array.isArray(_)||(_=[_]),_.forEach(_=>{this.__INSERT__(_,t)}),this.clear()}sort(_,t,e){let i="";t&&window.Intl&&(i+="\n let col = new Intl.Collator('zh')\n "),i+=e?"return arr.sort((b, a) => {":"return arr.sort((a, b) => {",i+=`\n let filter = function(val) {\n try {\n return val.${_} || ''\n } catch (err) {\n return ''\n }\n }\n `,t?window.Intl?i+="return col.compare(filter(a), filter(b))":i+="return (filter(a) + '').localeCompare(filter(b), 'zh')":i+="return filter(a) - filter(b)",i+="\n})",Function("arr",i).call(this,__STORE__[this.__name__]),this.clear()}update(_,t){let e=__STORE__[this.__name__],i=__STORE__[`${this.__name__}Dict`],r=i[_],n=e.indexOf(r);Object.assign(r,t),e.splice(n,1,r),i[_]=r}remove(_){let t=__STORE__[this.__name__],e=__STORE__[`${this.__name__}Dict`],i=e[_],r=t.indexOf(i);t.splice(r,1),delete e[_]}}Anot.store=window.store=AnotStore;export default AnotStore;
|
||||
const __STORE__={};function parse$And(_){let t="";for(let e in _){let i=_[e];switch(Anot.type(i)){case"object":if(i.$has){t+=`it.${e}.indexOf(${JSON.stringify(i.$has)}) > -1`;break}if(i.$in){t+=`${JSON.stringify(i.$in)}.indexOf(it.${e}) > -1`;break}if(i.$regex){t+=`${i.$regex}.test(it.${e})`;break}if(i.$lt||i.$lte){t+=`it.${e} <${i.$lte?"=":""} ${i.$lt||i.$lte}`,(i.$gt||i.$gte)&&(t+=` && it.${e} >${i.$gte?"=":""} ${i.$gt||i.$gte}`);break}if(i.$gt||i.$gte){t+=`it.${e} >${i.$gte?"=":""} ${i.$gt||i.$gte}`;break}if(i.$eq){t+=`it.${e} === ${i.$eq}`;break}default:t+=`it.${e} === ${JSON.stringify(_[e])}`}t+=" && "}return(t=t.slice(0,-4))||(t="true"),t}function parse$Or(_){let t="";return _.forEach(_=>{t+="(",t+=parse$And(_),t+=") || "}),t.slice(0,-4)}class AnotStore{constructor(_){Anot.hideProperty(this,"__name__",_),Anot.hideProperty(this,"__LAST_QUERY__",""),Anot.hideProperty(this,"__QUERY_HISTORY__",[]),__STORE__[_]||(__STORE__[_]=[],__STORE__[`${_}Dict`]={})}static collection(_){return new this(_)}__MAKE_FN__(_){let t="\n let result = [];\n let num = 0;\n for (let it of arr) {\n if(";return _.$or?t+=parse$Or(_.$or):t+=parse$And(_),t+="){\n result.push(it)\n num++\n if(limit > 0 && num >= limit){\n break\n }\n }\n }\n return result;",Function("arr","limit",t)}clear(_){this.__QUERY_HISTORY__=[],this.__LAST_QUERY__="",_&&(__STORE__[this.__name__]=[],__STORE__[`${this.__name__}Dict`]={})}getAll({filter:_,limit:t=[]}={}){const e=__STORE__[this.__name__];let i=[],r=!1;if(!e||!e.length)return i;if(t.length<1&&(t=[0]),t.length<2&&_&&(r=!0,t[0]>0&&t.unshift(0)),_){let n=JSON.stringify(_);if(this.__LAST_QUERY__===n)i=this.__QUERY_HISTORY__.slice.apply(this.__QUERY_HISTORY__,t);else{i=this.__MAKE_FN__(_)(e,r&&t[1]||0),r||(this.__LAST_QUERY__=n,this.__QUERY_HISTORY__=i,i=this.__QUERY_HISTORY__.slice.apply(this.__QUERY_HISTORY__,t))}}else i=e.slice.apply(e,t);return Anot.deepCopy(i)}get(_){const t=__STORE__[`${this.__name__}Dict`];return Anot.deepCopy(t[_])||null}count({filter:_}={}){return _?this.__LAST_QUERY__===JSON.stringify(_)?this.__QUERY_HISTORY__.length:this.getAll({filter:_,limit:[0]}).length:__STORE__[this.__name__].length}__INSERT__(_,t){let e=__STORE__[this.__name__],i=__STORE__[`${this.__name__}Dict`],r=_[t||"id"];i[r]?this.update(r,_):(e.push(_),i[r]=_)}insert(_,t){Array.isArray(_)||(_=[_]),_.forEach(_=>{this.__INSERT__(_,t)}),this.clear()}sort(_,t,e){let i="";t&&window.Intl&&(i+="\n let col = new Intl.Collator('zh')\n "),i+=e?"return arr.sort((b, a) => {":"return arr.sort((a, b) => {",i+=`\n let filter = function(val) {\n try {\n return val.${_} || ''\n } catch (err) {\n return ''\n }\n }\n `,t?window.Intl?i+="return col.compare(filter(a), filter(b))":i+="return (filter(a) + '').localeCompare(filter(b), 'zh')":i+="return filter(a) - filter(b)",i+="\n})",Function("arr",i).call(this,__STORE__[this.__name__]),this.clear()}update(_,t){let e=__STORE__[this.__name__],i=__STORE__[`${this.__name__}Dict`],r=i[_],n=e.indexOf(r);e.splice(n,1,t),i[_]=t}remove(_){let t=__STORE__[this.__name__],e=__STORE__[`${this.__name__}Dict`],i=e[_],r=t.indexOf(i);t.splice(r,1),delete e[_]}}Anot.store=window.store=AnotStore;export default AnotStore;
|
105
src/main.js
105
src/main.js
|
@ -22,112 +22,55 @@ const MIME_TYPES = {
|
|||
'.ico': 'image/ico'
|
||||
}
|
||||
|
||||
require('./tools/init')
|
||||
const createTray = require('./tools/tray')
|
||||
const createMenu = require('./tools/menu')
|
||||
const {
|
||||
createMainWindow,
|
||||
createErrorWindow,
|
||||
createDesktopLrcWindow,
|
||||
createMiniWindow
|
||||
} = require('./tools/windows')
|
||||
|
||||
/* ******************************* */
|
||||
/* **********修复环境变量*********** */
|
||||
/* ******************************* */
|
||||
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
|
||||
|
||||
app.windows = { createDesktopLrcWindow, createMiniWindow }
|
||||
const ROOT = __dirname
|
||||
const HOME = app.getPath('home')
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
app.commandLine.appendSwitch('--lang', 'zh-CN')
|
||||
app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required')
|
||||
|
||||
app.setPath('appData', path.resolve(HOME, '.sonist/'))
|
||||
protocol.registerStandardSchemes(['app'], { secure: true })
|
||||
|
||||
let appPath = app.getPath('appData')
|
||||
if (!fs.exists(appPath)) {
|
||||
fs.mkdir(appPath)
|
||||
fs.mkdir(path.join(appPath, 'lyrics'))
|
||||
fs.mkdir(path.join(appPath, 'cache'))
|
||||
fs.echo('{}', path.join(appPath, 'app.ini'))
|
||||
fs.echo('[]', path.join(appPath, 'music.db'))
|
||||
}
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
function createWindow() {
|
||||
// 创建浏览器窗口
|
||||
let win = new BrowserWindow({
|
||||
title: 'sonist',
|
||||
width: 1024,
|
||||
height: 640,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
icon: path.resolve(ROOT, './images/app.png'),
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
experimentalFeatures: true
|
||||
},
|
||||
show: false
|
||||
})
|
||||
|
||||
// 然后加载应用的 index.html。
|
||||
|
||||
win.loadURL('app://local/index.html')
|
||||
|
||||
win.on('ready-to-show', _ => {
|
||||
win.show()
|
||||
win.openDevTools()
|
||||
})
|
||||
|
||||
return win
|
||||
}
|
||||
/* ****************************************** */
|
||||
/* ************* init ******************* */
|
||||
/* ****************************************** */
|
||||
|
||||
// 创建窗口
|
||||
// 初始化应用
|
||||
app.once('ready', () => {
|
||||
// 注册协议
|
||||
protocol.registerBufferProtocol('app', (req, cb) => {
|
||||
let file = req.url.replace(/^app:\/\/local\//, '')
|
||||
let ext = path.extname(req.url)
|
||||
let buff = fs.cat(path.resolve(ROOT, file))
|
||||
cb({ data: buff, mimeType: MIME_TYPES[ext] })
|
||||
})
|
||||
// 修改app的UA
|
||||
session.defaultSession.setUserAgent(
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
|
||||
)
|
||||
|
||||
// 判断依赖
|
||||
exec('which ffprobe', (err, res) => {
|
||||
if (res) {
|
||||
session.defaultSession.setUserAgent(
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
|
||||
)
|
||||
|
||||
let win = createWindow()
|
||||
|
||||
let win = createMainWindow(path.resolve(ROOT, './images/app.png'))
|
||||
createTray(win)
|
||||
createMenu(win)
|
||||
// mac专属事件,点击dock栏图标,可激活窗口
|
||||
app.on('activate', _ => {
|
||||
if (win) {
|
||||
win.show()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
win = new BrowserWindow({
|
||||
width: 600,
|
||||
height: 360,
|
||||
skipTaskbar: true,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
resizable: false,
|
||||
titleBarStyle: 'hiddenInset'
|
||||
})
|
||||
win.setMenuBarVisibility(false)
|
||||
win.loadURL('app://local/depends.html')
|
||||
win.on('closed', _ => {
|
||||
app.exit()
|
||||
})
|
||||
createErrorWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('activate', _ => {
|
||||
if (win) {
|
||||
win.show()
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* 配置/DB通讯
|
||||
* @author yutent<yutent@doui.cc>
|
||||
* @date 2019/01/26 18:11:26
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { app, ipcMain } = require('electron')
|
||||
const path = require('path')
|
||||
const fs = require('iofs')
|
||||
|
||||
/* ********** 修复环境变量 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 HOME = app.getPath('home')
|
||||
|
||||
const APP_ROOT = path.resolve(HOME, '.sonist/')
|
||||
const LRC_DIR = path.join(APP_ROOT, 'lyrics')
|
||||
const CACHE_DIR = path.join(APP_ROOT, 'cache')
|
||||
const INIT_FILE = path.join(APP_ROOT, 'app.ini')
|
||||
const DB_FILE = path.join(APP_ROOT, 'music.db')
|
||||
|
||||
if (!fs.exists(APP_ROOT)) {
|
||||
fs.mkdir(APP_ROOT)
|
||||
fs.mkdir(LRC_DIR)
|
||||
fs.mkdir(CACHE_DIR)
|
||||
fs.echo('{}', INIT_FILE)
|
||||
fs.echo('[]', DB_FILE)
|
||||
}
|
||||
const SUPPORTED_EXTS = ['.mp3', '.webm', '.ogg', '.flac', '.m4a', '.aac']
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* --------------------- 事件开始 ------------------------- */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
// 获取应用配置
|
||||
ipcMain.on('get-init', (ev, val) => {
|
||||
let cache = fs.cat(INIT_FILE).toString('utf-8')
|
||||
cache = JSON.parse(cache)
|
||||
ev.returnValue = cache
|
||||
})
|
||||
|
||||
// 设置应用配置
|
||||
ipcMain.on('set-init', (ev, val) => {
|
||||
fs.echo(JSON.stringify(val), INIT_FILE)
|
||||
})
|
||||
|
||||
// 获取音乐数据库
|
||||
ipcMain.on('get-music', (ev, val) => {
|
||||
let cache = fs.cat(DB_FILE).toString('utf-8')
|
||||
cache = JSON.parse(cache)
|
||||
ev.returnValue = cache
|
||||
})
|
||||
|
||||
// 更新音乐数据库
|
||||
ipcMain.on('set-music', (ev, val) => {
|
||||
fs.echo(JSON.stringify(val), DB_FILE)
|
||||
})
|
||||
|
||||
/**
|
||||
* 保存歌词文件
|
||||
*/
|
||||
ipcMain.on('save-lrc', (ev, obj) => {
|
||||
fs.echo(obj.lrc, path.join(LRC_DIR, `${obj.id}.lrc`))
|
||||
})
|
||||
|
||||
/**
|
||||
* 读取歌词文件
|
||||
*/
|
||||
ipcMain.on('read-lrc', (ev, id) => {
|
||||
let file = path.join(LRC_DIR, `${id}.lrc`)
|
||||
if (fs.exists(file)) {
|
||||
ev.returnValue = fs.cat(file).toString('utf8')
|
||||
} else {
|
||||
ev.returnValue = null
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 保存音乐文件
|
||||
*/
|
||||
ipcMain.on('save-cache', (ev, obj) => {
|
||||
fs.echo(obj.data, path.join(CACHE_DIR, obj.file))
|
||||
})
|
||||
|
||||
/**
|
||||
* 扫描目录
|
||||
*/
|
||||
ipcMain.on('scan-dir', (ev, dir) => {
|
||||
if (fs.isdir(dir)) {
|
||||
let list = fs.ls(dir, true).filter(_ => {
|
||||
if (fs.isdir(_)) {
|
||||
return false
|
||||
} else {
|
||||
let { ext, name } = path.parse(_)
|
||||
if (!ext || name.startsWith('.')) {
|
||||
return false
|
||||
}
|
||||
return SUPPORTED_EXTS.includes(ext)
|
||||
}
|
||||
})
|
||||
ev.returnValue = list
|
||||
} else {
|
||||
ev.returnValue = null
|
||||
}
|
||||
})
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* 各种窗口创建
|
||||
* @author yutent<yutent@doui.cc>
|
||||
* @date 2019/01/26 18:28:22
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
/**
|
||||
* 应用主窗口
|
||||
*/
|
||||
exports.createMainWindow = function(icon) {
|
||||
// 创建浏览器窗口
|
||||
let win = new BrowserWindow({
|
||||
title: 'sonist',
|
||||
width: 1024,
|
||||
height: 640,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
icon,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
experimentalFeatures: true
|
||||
},
|
||||
show: false
|
||||
})
|
||||
|
||||
// 然后加载应用的 index.html。
|
||||
|
||||
win.loadURL('app://local/index.html')
|
||||
|
||||
win.on('ready-to-show', _ => {
|
||||
win.show()
|
||||
win.openDevTools()
|
||||
})
|
||||
|
||||
return win
|
||||
}
|
||||
|
||||
/**
|
||||
* 依赖异常显示窗口
|
||||
*/
|
||||
exports.createErrorWindow = function() {
|
||||
let win = new BrowserWindow({
|
||||
width: 600,
|
||||
height: 360,
|
||||
skipTaskbar: true,
|
||||
maximizable: false,
|
||||
minimizable: false,
|
||||
resizable: false,
|
||||
titleBarStyle: 'hiddenInset'
|
||||
})
|
||||
win.setMenuBarVisibility(false)
|
||||
win.loadURL('app://local/depends.html')
|
||||
win.on('closed', _ => {
|
||||
app.exit()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 桌面歌词窗口
|
||||
*/
|
||||
exports.createDesktopLrcWindow = function(screen) {
|
||||
let win = new BrowserWindow({
|
||||
title: '',
|
||||
width: 1024,
|
||||
height: 100,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
alwaysOnTop: true,
|
||||
x: (screen.size.width - 1024) / 2,
|
||||
y: screen.size.height - 100,
|
||||
skipTaskbar: true,
|
||||
hasShadow: false,
|
||||
thickFrame: false,
|
||||
transparent: true,
|
||||
show: false
|
||||
})
|
||||
|
||||
win.loadURL('app://local/desktop-lrc.html')
|
||||
return win
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用迷你窗口
|
||||
*/
|
||||
exports.createMiniWindow = function(screen) {
|
||||
let win = new BrowserWindow({
|
||||
title: '',
|
||||
width: 320,
|
||||
height: 60,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
alwaysOnTop: true,
|
||||
x: screen.size.width - 320,
|
||||
y: 0,
|
||||
skipTaskbar: true,
|
||||
show: false
|
||||
})
|
||||
|
||||
// win.loadURL('http://127.0.0.1:10240/mini-win.html')
|
||||
win.loadURL('app://local/mini-win.html')
|
||||
return win
|
||||
}
|
Reference in New Issue