From 4bcc894ec3827a0ff73e337401edc0a607f232a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Sat, 26 Jan 2019 22:19:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=A4=A7=E6=B3=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 8 +-- src/js/app.js | 34 ++++------ src/js/modules/extra-win.js | 53 ---------------- src/js/modules/ktv.js | 17 ++--- src/js/modules/local.js | 54 ++++++---------- src/js/modules/profile.js | 21 +++---- src/lib/css/layer-normal.css | 2 +- src/lib/layer/index.js | 2 +- src/lib/lyrics/index.js | 23 +++---- src/lib/store/index.js | 2 +- src/main.js | 105 +++++++------------------------ src/tools/init.js | 117 +++++++++++++++++++++++++++++++++++ src/tools/windows.js | 106 +++++++++++++++++++++++++++++++ 13 files changed, 306 insertions(+), 238 deletions(-) delete mode 100644 src/js/modules/extra-win.js create mode 100644 src/tools/init.js create mode 100644 src/tools/windows.js diff --git a/package.json b/package.json index a0d3b91..2724971 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/js/app.js b/src/js/app.js index fc5ad85..e395554 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -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) }) } } diff --git a/src/js/modules/extra-win.js b/src/js/modules/extra-win.js deleted file mode 100644 index a41c9f3..0000000 --- a/src/js/modules/extra-win.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * 额外的小窗口 - * @author yutent - * @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 -} diff --git a/src/js/modules/ktv.js b/src/js/modules/ktv.js index 9c952d0..706ca4d 100644 --- a/src/js/modules/ktv.js +++ b/src/js/modules/ktv.js @@ -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('歌词应用成功...') diff --git a/src/js/modules/local.js b/src/js/modules/local.js index bfe9b4e..92bd17c 100644 --- a/src/js/modules/local.js +++ b/src/js/modules/local.js @@ -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 { diff --git a/src/js/modules/profile.js b/src/js/modules/profile.js index bd1aff3..7822e0c 100644 --- a/src/js/modules/profile.js +++ b/src/js/modules/profile.js @@ -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('保存成功') diff --git a/src/lib/css/layer-normal.css b/src/lib/css/layer-normal.css index 8b677e6..f1fcf30 100644 --- a/src/lib/css/layer-normal.css +++ b/src/lib/css/layer-normal.css @@ -1 +1 @@ -.do-layer{width:auto;height:auto}.do-layer a{text-decoration:none}.do-layer .layer-box{position:absolute;z-index:65535;opacity:0}.do-layer .layer-box.shift{transition:all .5s ease-out}.do-layer .layer-box.__tc{top:0;left:50%}.do-layer .layer-box.__tl{top:0;left:0}.do-layer .layer-box.__tr{top:0;left:100%}.do-layer .layer-box.__ct{top:50%;left:50%}.do-layer .layer-box.__cc{top:47.5%;left:50%}.do-layer .layer-box.__bc{top:100%;left:50%}.do-layer .layer-box.__bl{top:100%;left:0}.do-layer .layer-box.__br{top:100%;left:100%}.do-layer .layer-box.scale{transform:scale(1.02);transition:transform .1s linear}.do-layer .layer-box.skin-normal{padding:15px 10px;border-radius:3px;color:#666;font-size:14px;box-shadow:0 5px 20px rgba(0,0,0,0.3)}.do-layer .layer-box.skin-normal .layer-title{width:100%;height:43px;padding:0 10px;line-height:43px;font-size:16px;color:#526273}.do-layer .layer-box.skin-normal .layer-content{position:relative;width:100%;height:auto;min-height:50px;word-break:break-all;word-wrap:break-word}.do-layer .layer-box.skin-normal .layer-content .prompt-value{width:100%;height:30px;padding:0 8px;border:1px solid #ddd;border-radius:3px}.do-layer .layer-box.skin-normal .layer-content .prompt-value.alert{border-color:#eb3b48}.do-layer .layer-box.skin-normal .layer-content .prompt-value:focus{border-color:#19b491}.do-layer .layer-box.skin-normal .layer-content .msg-box{line-height:30px}.do-layer .layer-box.skin-normal .layer-ctrl{width:100%;height:40px;padding:5px 0;line-height:30px;font-size:14px;color:#454545;text-align:right}.do-layer .layer-box.skin-normal .layer-ctrl a{overflow:hidden;position:relative;display:inline-block;width:auto;min-width:60px;height:30px;margin-left:5px;padding:0 10px;color:#19b491;text-align:center;cursor:pointer}.do-layer .layer-box.skin-normal .layer-ctrl a::before{position:absolute;left:-50%;top:-50%;z-index:-1;display:block;width:200%;height:200%;border-radius:50%;background:#f3f5fb;content:"";opacity:0;transform:scale(0, 0);transition:opacity 1.3s cubic-bezier(0.23, 1, 0.32, 1),transform 1.3s cubic-bezier(0.23, 1, 0.32, 1)}.do-layer .layer-box.skin-normal .layer-ctrl a:hover::before{opacity:1;transform:scale(1, 0.8)}.do-layer .layer-box.skin-normal .layer-ctrl a:active{background:#e8ebf4}.do-layer .layer-box.type-1,.do-layer .layer-box.type-2,.do-layer .layer-box.type-3{max-width:600px;min-width:300px}.do-layer .layer-box.type-1 .layer-content,.do-layer .layer-box.type-2 .layer-content,.do-layer .layer-box.type-3 .layer-content{padding:10px}.do-layer .layer-box.type-4{padding:0}.do-layer .layer-box.type-4 .frame-box{display:block;width:100%;height:100%;margin:0;padding:0;border:0;resize:none}.do-layer .layer-box.type-5{visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;color:#fff;background:rgba(0,0,0,0.5);box-shadow:none}.do-layer .layer-box.type-5 i.arrow{position:absolute;width:0;height:0;border:6px solid transparent;content:""}.do-layer .layer-box.type-5 i.offset-top{left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-bottom{left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-top-left{right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-bottom-left{right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 .layer-content{min-height:20px;margin:0}.do-layer .layer-box.type-6{z-index:65539;box-shadow:none;background:transparent}.do-layer .layer-box.type-toast{position:fixed;min-width:10px;padding:0;background:transparent}.do-layer .layer-box.type-toast .layer-content{min-height:40px;height:40px}.do-layer .layer-box.type-toast .toast-box{display:inline-block;position:relative;min-height:40px;padding:5px 12px 5px 50px;line-height:28px;border-radius:3px;word-break:break-all}.do-layer .layer-box.type-toast .toast-box.style-info{border:1px solid #19b491;background:#edfbf8;color:#16967a}.do-layer .layer-box.type-toast .toast-box.style-warn{border:1px solid #f39c12;background:#fffbed;color:#e67e22}.do-layer .layer-box.type-toast .toast-box.style-deny{border:1px solid #eb3b48;background:#fffbed;color:#ce3742}.do-layer .layer-box.type-toast .toast-box>i{position:absolute;left:12px;top:5px;line-height:28px;font-size:26px}.do-layer .layer-box .loading{position:relative;width:100px;height:100px;margin:auto}.do-layer .layer-box .loading .dot-box{position:absolute;display:block}.do-layer .layer-box .loading.style-1 .dot-box,.do-layer .layer-box .loading.style-2 .dot-box{width:70%;height:70%;margin:15%;line-height:70px;font-size:70px;text-align:center}.do-layer .layer-box .loading.style-1 .dot-box i,.do-layer .layer-box .loading.style-2 .dot-box i{display:block;width:100%;height:100%}.do-layer .layer-box .loading.style-1 .dot-box{animation:circle .8s infinite linear}.do-layer .layer-box .loading.style-2 .dot-box{animation:round .6s infinite linear}.do-layer .layer-box .loading.style-3{height:50px}.do-layer .layer-box .loading.style-3 .dot-box{width:100%;height:100%}.do-layer .layer-box .loading.style-3 .dot-box i{float:left;display:block;width:10px;height:100%;margin:0 5px;background:#16967a;animation:bounce 1s infinite ease-in-out;transform:scaleY(0.6)}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(2){animation-delay:.1s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(3){animation-delay:.2s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(4){animation-delay:.3s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(5){animation-delay:.4s}.do-layer .layer-box .loading.style-4 .dot-box{width:60%;height:60%;margin:20%}.do-layer .layer-box .loading.style-4 .dot-box i{position:absolute;display:block;width:60px;height:60px;animation:circle2 2s infinite ease-in-out;transform:rotate(45deg)}.do-layer .layer-box .loading.style-4 .dot-box i::before{display:block;width:8px;height:8px;background:#16967a;border-radius:50%;content:""}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(2){animation-delay:.1s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(3){animation-delay:.2s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(4){animation-delay:.3s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(5){animation-delay:.4s}.do-layer .layer-box .loading.style-5 .dot-box{width:90%;height:90%;margin:5%}.do-layer .layer-box .loading.style-5 .dot-box i{float:left;display:block;width:30px;height:30px;background:#16967a;animation:grid 1.5s infinite linear}.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(4),.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(8){animation-delay:.2s}.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(1),.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(5),.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(9){animation-delay:.3s}.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(2),.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(6){animation-delay:.4s}.do-layer .layer-box .loading.style-5 .dot-box i:nth-child(3){animation-delay:.5s}.do-layer.mask{position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:transparent}.do-layer.mask.shift{transition:all .5s ease-out}.do-layer.mask.inner{position:absolute}.do-layer:active{z-index:65536}.do-layer__tips{visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,0.5)}.do-layer__tips i.arrow{position:absolute;width:0;height:0;border:6px solid transparent;content:""}.do-layer__tips i.offset-top{left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-bottom{left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-top-left{right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-bottom-left{right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer__tips .layer-content{min-height:20px;margin:0}@keyframes circle{to{transform:rotate(360deg)}}@keyframes circle2{70%,to{transform:rotate(405deg)}}@keyframes round{from,24.99%,to{transform:rotate(0deg)}25%,49.99%{transform:rotate(90deg)}50%,74.99%{transform:rotate(180deg)}75%,99.99%{transform:rotate(270deg)}}@keyframes bounce{25%{transform:scaleY(1.3)}50%{transform:scaleY(0.6)}}@keyframes grid{36%{transform:scale(0.1);opacity:.3}60%{transform:scale(1);opacity:1}}@media screen and (max-width: 480px){.do-layer .layer-box.type-1,.do-layer .layer-box.type-2,.do-layer .layer-box.type-3,.do-layer .layer-box.type-4,.do-layer .layer-box.type-7{width:90%}} +.do-layer{width:auto;height:auto}.do-layer a{text-decoration:none}.do-layer .layer-box{position:absolute;z-index:65535;opacity:0}.do-layer .layer-box.shift{transition:all .5s ease-out}.do-layer .layer-box.__tc{top:0;left:50%}.do-layer .layer-box.__tl{top:0;left:0}.do-layer .layer-box.__tr{top:0;left:100%}.do-layer .layer-box.__ct{top:50%;left:50%}.do-layer .layer-box.__cc{top:47.5%;left:50%}.do-layer .layer-box.__bc{top:100%;left:50%}.do-layer .layer-box.__bl{top:100%;left:0}.do-layer .layer-box.__br{top:100%;left:100%}.do-layer .layer-box.scale{transform:scale(1.02);transition:transform .1s linear}.do-layer .layer-box.skin-normal{padding:15px 10px;border-radius:3px;color:#666;font-size:14px;box-shadow:0 5px 20px rgba(0,0,0,0.3)}.do-layer .layer-box.skin-normal .layer-title{width:100%;height:43px;padding:0 10px;line-height:43px;font-size:16px;color:#526273}.do-layer .layer-box.skin-normal .layer-content{position:relative;width:100%;height:auto;min-height:50px;word-break:break-all;word-wrap:break-word}.do-layer .layer-box.skin-normal .layer-content .prompt-value{width:100%;height:30px;padding:0 8px;border:1px solid #ddd;border-radius:3px}.do-layer .layer-box.skin-normal .layer-content .prompt-value.alert{border-color:#eb3b48}.do-layer .layer-box.skin-normal .layer-content .prompt-value:focus{border-color:#19b491}.do-layer .layer-box.skin-normal .layer-content .msg-box{line-height:30px}.do-layer .layer-box.skin-normal .layer-ctrl{width:100%;height:40px;padding:5px 0;line-height:30px;font-size:14px;color:#454545;text-align:right}.do-layer .layer-box.skin-normal .layer-ctrl a{overflow:hidden;position:relative;display:inline-block;width:auto;min-width:60px;height:30px;margin-left:5px;padding:0 10px;color:#19b491;text-align:center;cursor:pointer}.do-layer .layer-box.skin-normal .layer-ctrl a::before{position:absolute;left:-50%;top:-50%;z-index:-1;display:block;width:200%;height:200%;border-radius:50%;background:#f3f5fb;content:"";opacity:0;transform:scale(0, 0);transition:opacity 1.3s cubic-bezier(0.23, 1, 0.32, 1),transform 1.3s cubic-bezier(0.23, 1, 0.32, 1)}.do-layer .layer-box.skin-normal .layer-ctrl a:hover::before{opacity:1;transform:scale(1, 0.8)}.do-layer .layer-box.skin-normal .layer-ctrl a:active{background:#e8ebf4}.do-layer .layer-box.type-1,.do-layer .layer-box.type-2,.do-layer .layer-box.type-3{max-width:600px;min-width:300px}.do-layer .layer-box.type-1 .layer-content,.do-layer .layer-box.type-2 .layer-content,.do-layer .layer-box.type-3 .layer-content{padding:10px}.do-layer .layer-box.type-4{padding:0}.do-layer .layer-box.type-4 .frame-box{display:block;width:100%;height:100%;margin:0;padding:0;border:0;resize:none}.do-layer .layer-box.type-5{visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;color:#fff;background:rgba(0,0,0,0.5);box-shadow:none}.do-layer .layer-box.type-5 i.arrow{position:absolute;width:0;height:0;border:6px solid transparent;content:""}.do-layer .layer-box.type-5 i.offset-top{left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-bottom{left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-top-left{right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 i.offset-bottom-left{right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer .layer-box.type-5 .layer-content{min-height:20px;margin:0}.do-layer .layer-box.type-6{z-index:65539;box-shadow:none;background:transparent}.do-layer .layer-box.type-toast{position:fixed;min-width:10px;padding:0;background:transparent}.do-layer .layer-box.type-toast .layer-content{min-height:40px;height:40px}.do-layer .layer-box.type-toast .toast-box{display:inline-block;position:relative;min-height:40px;padding:5px 12px 5px 50px;line-height:28px;border-radius:3px;word-break:break-all}.do-layer .layer-box.type-toast .toast-box.style-info{border:1px solid #19b491;background:#edfbf8;color:#16967a}.do-layer .layer-box.type-toast .toast-box.style-warn{border:1px solid #f39c12;background:#fffbed;color:#e67e22}.do-layer .layer-box.type-toast .toast-box.style-deny{border:1px solid #eb3b48;background:#fffbed;color:#ce3742}.do-layer .layer-box.type-toast .toast-box>i{position:absolute;left:12px;top:5px;line-height:28px;font-size:26px}.do-layer .layer-box .loading{position:relative;width:100px;height:100px;margin:auto}.do-layer .layer-box .loading .dot-box{position:absolute;display:block}.do-layer .layer-box .loading.style-1 .dot-box{width:70%;height:70%;margin:15%;line-height:70px;font-size:70px;text-align:center}.do-layer .layer-box .loading.style-1 .dot-box i{display:block;width:100%;height:100%}.do-layer .layer-box .loading.style-1 .dot-box{animation:circle .8s infinite linear}.do-layer .layer-box .loading.style-2{height:50px}.do-layer .layer-box .loading.style-2 .dot-box{width:100%;height:100%}.do-layer .layer-box .loading.style-2 .dot-box i{float:left;display:block;width:10px;height:100%;margin:0 5px;background:#16967a;animation:bounce 1s infinite ease-in-out;transform:scaleY(0.6)}.do-layer .layer-box .loading.style-2 .dot-box i:nth-child(2){animation-delay:.1s}.do-layer .layer-box .loading.style-2 .dot-box i:nth-child(3){animation-delay:.2s}.do-layer .layer-box .loading.style-2 .dot-box i:nth-child(4){animation-delay:.3s}.do-layer .layer-box .loading.style-2 .dot-box i:nth-child(5){animation-delay:.4s}.do-layer .layer-box .loading.style-3 .dot-box{width:60%;height:60%;margin:20%}.do-layer .layer-box .loading.style-3 .dot-box i{position:absolute;display:block;width:60px;height:60px;animation:circle2 2s infinite ease-in-out;transform:rotate(45deg)}.do-layer .layer-box .loading.style-3 .dot-box i::before{display:block;width:8px;height:8px;background:#16967a;border-radius:50%;content:""}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(2){animation-delay:.1s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(3){animation-delay:.2s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(4){animation-delay:.3s}.do-layer .layer-box .loading.style-3 .dot-box i:nth-child(5){animation-delay:.4s}.do-layer .layer-box .loading.style-4 .dot-box{width:90%;height:90%;margin:5%}.do-layer .layer-box .loading.style-4 .dot-box i{float:left;display:block;width:30px;height:30px;background:#16967a;animation:grid 1.5s infinite linear}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(4),.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(8){animation-delay:.2s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(1),.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(5),.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(9){animation-delay:.3s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(2),.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(6){animation-delay:.4s}.do-layer .layer-box .loading.style-4 .dot-box i:nth-child(3){animation-delay:.5s}.do-layer.mask{position:fixed;z-index:65534;left:0;top:0;width:100%;height:100%;background:transparent}.do-layer.mask.shift{transition:all .5s ease-out}.do-layer.mask.inner{position:absolute}.do-layer:active{z-index:65536}.do-layer__tips{visibility:hidden;position:fixed;z-index:65534;min-width:75px;max-width:600px;padding:10px;line-height:1.5;border-radius:3px;font-size:14px;color:#fff;background:rgba(0,0,0,0.5)}.do-layer__tips i.arrow{position:absolute;width:0;height:0;border:6px solid transparent;content:""}.do-layer__tips i.offset-top{left:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-bottom{left:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-top-left{right:5px;bottom:-14px;border-top:8px solid rgba(0,0,0,0.5)}.do-layer__tips i.offset-bottom-left{right:5px;top:-14px;border-bottom:8px solid rgba(0,0,0,0.5)}.do-layer__tips .layer-content{min-height:20px;margin:0}@keyframes circle{to{transform:rotate(360deg)}}@keyframes circle2{70%,to{transform:rotate(405deg)}}@keyframes bounce{25%{transform:scaleY(1.3)}50%{transform:scaleY(0.6)}}@keyframes grid{36%{transform:scale(0.1);opacity:.3}60%{transform:scale(1);opacity:1}}@media screen and (max-width: 480px){.do-layer .layer-box.type-1,.do-layer .layer-box.type-2,.do-layer .layer-box.type-3,.do-layer .layer-box.type-4,.do-layer .layer-box.type-7{width:90%}} diff --git a/src/lib/layer/index.js b/src/lib/layer/index.js index c220319..fc808e9 100644 --- a/src/lib/layer/index.js +++ b/src/lib/layer/index.js @@ -1 +1 @@ -"use strict";import "../drag/index.js";importCss("/css/layer-normal.css");Anot.ui.layer="1.0.0-normal";const LANGUAGES={en:{TITLE:"Dialog",YES_BTN:"OK",NO_BTN:"Cancel",ERROR:"The layer instance is not exists",NEED_CONTAINER:'layer "tips" require a DOM object as container'},zh:{TITLE:"提示",YES_BTN:"确定",NO_BTN:"取消",ERROR:"要关闭的layer实例不存在",NEED_CONTAINER:"tips类型需要指定一个元素节点作为容器"},"zh-TW":{TITLE:"提示",YES_BTN:"確定",NO_BTN:"取消",ERROR:"要關閉的layer實例不存在",NEED_CONTAINER:"tips类型需要指定一個元素節點作爲容器"}};LANGUAGES["zh-CN"]=LANGUAGES.zh;const lang=LANGUAGES[window.__ENV_LANG__||navigator.language]||LANGUAGES.en;let layerDom={},layerObj={},unique=null,lid=0,defconf={type:1,background:"#fff",mask:!0,maskClose:!1,maskColor:null,radius:"0px",area:["auto","auto"],title:lang.TITLE,menubar:!0,content:"",fixed:!1,shift:"cc",offset:[],btns:[lang.YES_BTN,lang.NO_BTN]};const $doc=Anot(document),uuid=function(){return"layer-"+lid++},close=function(e){if("string"!=typeof e&&"number"!=typeof e)return Anot.error(lang.ERROR);if(/^layerwrap\-/.test(e)||layerObj["layerwrap-"+e])try{if(e=(layerObj["layerwrap-"+e]?"layerwrap-":"")+e,!layerObj[e].show)return;layerObj[e].parentElem.replaceChild(layerObj[e].wrap,layerDom[e][0]),layerObj[e].wrap.style.display="none",layerObj[e].show=!1}catch(e){}else{unique=null;try{layerDom[e][0].classList.add("shift"),layerDom[e][1].classList.add("shift"),layerDom[e][0].style.opacity="",layerDom[e][1].style.opacity=0,setTimeout(function(){layerDom[e][0].parentNode.removeChild(layerDom[e][0]),delete layerDom[e],delete Anot.vmodels[e]},200)}catch(e){}}document.body.style.overflow=""},repeat=function(e,t){let o=0,s="";for(;o{this.$refs.layer.classList.remove("scale")},100)},onMaskClick:function(){this.type<4&&!this.maskClose?this.shake():this.maskClose&&this.close()},handleConfirm:function(){if(3===this.type&&!this.prompt)return this.shake();if("function"==typeof this.props.yes){let e=[this.$id];3===this.type&&e.unshift(this.prompt),this.props.yes.apply(this,e)}else this.close()},handleCancel:function(){"function"==typeof this.props.no?this.props.no.call(this,this.$id):this.close()},close:function(){close(this.$id)},cancelBubble:function(e){e.cancelBubble=!0}},mounted:function(){"function"==typeof this.props.success&&this.props.success.call(this)}},4===this.init.state.type&&(this.init.methods.autoSize=function(){let{layer:e,frame:t}=this.$refs;t.onload=function(){setTimeout(function(){try{let o=t.contentWindow.document.body,{clientWidth:s,clientHeight:n}=o;Anot(e).css({width:s,height:n,marginLeft:-s/2,marginTop:-n/2}),Anot(t).css({height:n})}catch(e){}},500)}}),this}create(){let{state:e,$id:t}=this.init,o=document.createElement("div"),s=document.createElement("div");if(o.setAttribute("anot",t),o.setAttribute(":click","onMaskClick"),o.classList.add("do-layer"),e.mask&&(o.classList.add("mask"),e.container&&e.container!==document.body&&o.classList.add("inner")),e.maskColor&&(o.style.background=e.maskColor),s.classList.add("layer-box"),s.classList.add("skin-normal"),e.extraClass&&(s.classList.add(e.extraClass),delete e.extraClass),"string"==typeof e.shift)s.classList.add("__"+e.shift);else for(let t in e.shift){let o=e.shift[t];o+=isFinite(o)?"px":"",s.style.cssText+=`${t}: ${o};`}e.toast?s.classList.add("type-toast"):s.classList.add("type-"+e.type),s.setAttribute("ref","layer"),s.setAttribute(":click","cancelBubble"),s.style.cssText+="border-radius:"+e.radius+"px",e.menubar||e.fixed||(s.setAttribute(":drag",""),s.setAttribute("data-limit","window"));var n="";"auto"!==e.area[0]&&(n+="width: "+e.area[0]+";"),"auto"!==e.area[1]&&(n+="height: "+e.area[1]+";");let i="";return 5===e.type&&(i+=''),s.innerHTML=`\n ${this.mkMenubar()}\n \n\n ${6===e.type?this.mkLoading(e.load):""}\n \n ${this.mkCtrl()}\n ${i}\n `,delete e.wrap,o.appendChild(s),[o,s]}mkLoading(e){return`\n
\n \n ${repeat(1===e?'':2===e?'':"",this.dot[e])}\n \n
\n `}mkMenubar(){let{menubar:e,fixed:t}=this.init.state,o="";return e&&(o=`\n
\n
\n `),o}mkCtrl(){let{type:e}=this.init.state;if(e>3)return"";{let t="",o='\n \n ';return e>1&&(o='\n \n '+o),t=`\n
\n ${o}\n
\n `}}append(){let{state:e,$id:t}=this.init,o=e.container;return e.type<4&&(unique&&close(unique),unique=t),layerDom[t]=this.create(),delete e.toast,this.toast=!0,o||(o=document.body),o.appendChild(layerDom[t][0]),this.vm=Anot(this.init),this}show(){let{state:e,$id:t}=this.init,o=(this.vm,e.container);setTimeout(function(){let s={background:e.background},n=getComputedStyle(layerDom[t][1]);if(5===e.type){s.color=e.color,s.opacity=1;let i=Anot(o),a=i[0].querySelector(".arrow"),r=i.innerWidth(),l=i.innerHeight(),c=i.offset().left-$doc.scrollLeft(),d=i.offset().top-$doc.scrollTop(),p=parseInt(n.width),f=parseInt(n.height),y=["top"];Anot(layerDom[t][1]).css(s),i.bind("mouseenter",o=>{let s={visibility:"visible"};c=i.offset().left-$doc.scrollLeft(),(d=i.offset().top-$doc.scrollTop())+18window.innerWidth?(s.left=c+.3*r-p,y[1]="left"):s.left=c+.7*r,a.classList.add("offset-"+y.join("-")),Anot(layerDom[t][1]).css(s)}),i.bind("mouseleave",()=>{setTimeout(()=>{a.classList.remove("offset-"+y.join("-")),y=["top"],a.style.borderBottomColor="",a.style.borderTopColor="",layerDom[t][1].style.visibility="hidden"},100)})}else{let o={opacity:1};e.offset?(o.top=fixOffset(e.offset[0]),o.right=fixOffset(e.offset[1]),o.bottom=fixOffset(e.offset[2]),o.left=fixOffset(e.offset[3]),"auto"===o.left&&"auto"===o.right&&(o.left="50%",s.marginLeft=-parseInt(n.width)/2),"auto"===o.top&&"auto"===o.bottom&&(o.top="50%",s.marginTop=-parseInt(n.height)/2)):s=Object.assign(s,{marginLeft:-parseInt(n.width)/2,marginTop:-parseInt(n.height)/2}),Anot(layerDom[t][1]).css(s),setTimeout(()=>{document.body.style.overflow="hidden",layerDom[t][1].classList.add("shift"),setTimeout(s=>{Anot(layerDom[t][1]).css(o),setTimeout(o=>{try{layerDom[t][1].classList.remove("shift"),layerDom[t][1].classList.remove("__"+e.shift)}catch(e){}},500)},50)},50)}},4),e.type>3&&(e.timeout>0?(clearTimeout(this.timeout),this.timeout=setTimeout(()=>{clearTimeout(this.timeout),close(t),6===e.type&&this.vm.props.yes.call(this.vm,t)},e.timeout)):6===e.type&&this.vm.props.yes.call(this.vm,t))}}const _layer={alert(e,t,o){let s={content:e,fixed:!0};return"function"==typeof t?s.yes=t:(t&&(s.title=t+""),o&&"function"==typeof o&&(s.yes=o)),_layer.open(s)},confirm(e,t,o,s){let n={content:e,fixed:!0,type:2};return"function"==typeof t?(n.yes=t,"function"==typeof o&&(n.no=o)):(t&&(n.title=t+""),o&&"function"==typeof o&&(n.yes=o),s&&"function"==typeof s&&(n.no=s)),_layer.open(n)},frame(e,t={}){let o={content:``,menubar:!1,maskClose:!0,type:4,...t};return _layer.open(o)},toast(e,t="info",o=2500){switch("number"==typeof t&&(o=t,t="info"),t){case"info":case"warn":break;case"error":t="deny";break;default:t="info"}let s={content:`\n \n \n ${e}\n `,menubar:!1,mask:!1,type:7,shift:"tc",timeout:o,offset:[50,"auto"],fixed:!0,toast:!0};return _layer.open(s)},load:(e,t,o)=>(e=(e>>>=0)<1?1:e>5?5:e,"function"==typeof t?(o=t,t=null):(t instanceof HTMLElement||(t=null),"function"!=typeof o&&(o=Anot.noop)),_layer.open({container:t,type:6,load:e,yes:o,menubar:!1,background:"none",shift:"ct",fixed:!0})),tips:(e,t,o={})=>t instanceof HTMLElement?(o.background||(o.background="rgba(0,0,0,.5)"),o.color||(o.color="#fff"),Object.assign(o,{container:t,content:e,type:5,fixed:!0,mask:!1,menubar:!1,timeout:0}),_layer.open(o)):Anot.error(lang.NEED_CONTAINER),prompt(e,t){if("function"!=typeof t)return console.error("argument [callback] requires a function, but "+typeof t+" given");let o={type:3,prompt:"",title:e,content:'',fixed:!0,yes:t};return _layer.open(o)},close:close,open(e){if("string"==typeof e){if(layerObj[e="layerwrap-"+e])return layerObj[e].show?e:(layerObj[e].show=!0,layerObj[e].parentElem.appendChild(layerDom[e][0]),layerDom[e][0].querySelector(".layer-content").appendChild(layerObj[e].wrap),layerObj[e].wrap.style.display="",Anot.vmodels[e]||Anot(layerObj[e].obj.init),layerObj[e].obj.show(),e);throw new Error(lang.ERROR)}return new __layer__(e).init.$id},version:Anot.ui.layer};Anot.directive("layer",{priority:8090,init:function(e){e.element.removeAttribute(e.name),e.param&&"tips"===e.param||(e.param="",e.element.style.display="none")},update:function(e){if(!e)return console.error(this),console.error(`SyntaxError: Unexpected [${this.name}=${this.expr}]`);let t=Object.assign({type:7,wrap:!0},this.element.dataset);if(this.param){if("tips"===this.param){let o=document.createElement("div"),s=document.createElement("span"),n=document.createElement("i");o.className="do-layer__tips",s.className="layer-content",n.className="arrow",s.textContent=e,o.appendChild(s),o.appendChild(n),this.element.appendChild(o),t.color&&(i.color=t.color),t.color&&(i.background=t.background);let i={},a=getComputedStyle(o),r=Anot(this.element),l=r.innerWidth(),c=r.innerHeight(),d=r.offset().left-$doc.scrollLeft(),p=r.offset().top-$doc.scrollTop(),f=parseInt(a.width),y=parseInt(a.height),u=["top"];Anot(o).css(i),r.bind("mouseenter",e=>{let s={visibility:"visible"};d=r.offset().left-$doc.scrollLeft(),(p=r.offset().top-$doc.scrollTop())+18window.innerWidth?(s.left=d+.3*l-f,u[1]="left"):s.left=d+.7*l,n.classList.add("offset-"+u.join("-")),Anot(o).css(s)}),r.bind("mouseleave",()=>{setTimeout(()=>{n.classList.remove("offset-"+u.join("-")),u=["top"],n.style.borderBottomColor="",n.style.borderTopColor="",o.style.visibility="hidden"},100)})}}else{let o={$id:"layerwrap-"+e,state:t,props:{}};t.hasOwnProperty("area")&&(t.area=t.area.split(",")),t.hasOwnProperty("offset")&&(t.offset=t.offset.split(",")),t.hasOwnProperty("btns")&&(t.btns=t.btns.split(",")),t.hasOwnProperty("menubar")||(t.menubar=!1);let s=(new __layer__).__init__(o);for(let e in this.element.dataset)delete this.element.dataset[e];layerObj[s.init.$id]={obj:s,parentElem:this.element.parentNode,wrap:this.element,show:!1},layerDom[s.init.$id]=s.create()}}}),window.layer=_layer;export default _layer; \ No newline at end of file +"use strict";import "../drag/index.js";importCss("/css/layer-normal.css");Anot.ui.layer="1.0.0-normal";const LANGUAGES={en:{TITLE:"Dialog",YES_BTN:"OK",NO_BTN:"Cancel",ERROR:"The layer instance is not exists",NEED_CONTAINER:'layer "tips" require a DOM object as container'},zh:{TITLE:"提示",YES_BTN:"确定",NO_BTN:"取消",ERROR:"要关闭的layer实例不存在",NEED_CONTAINER:"tips类型需要指定一个元素节点作为容器"},"zh-TW":{TITLE:"提示",YES_BTN:"確定",NO_BTN:"取消",ERROR:"要關閉的layer實例不存在",NEED_CONTAINER:"tips类型需要指定一個元素節點作爲容器"}};LANGUAGES["zh-CN"]=LANGUAGES.zh;const lang=LANGUAGES[window.__ENV_LANG__||navigator.language]||LANGUAGES.en;let layerDom={},layerObj={},unique=null,lid=0,defconf={type:1,background:"#fff",mask:!0,maskClose:!1,maskColor:null,radius:"0px",area:["auto","auto"],title:lang.TITLE,menubar:!0,content:"",fixed:!1,shift:"cc",offset:[],btns:[lang.YES_BTN,lang.NO_BTN]};const $doc=Anot(document),uuid=function(){return"layer-"+lid++},close=function(e){if("string"!=typeof e&&"number"!=typeof e)return Anot.error(lang.ERROR);if(/^layerwrap\-/.test(e)||layerObj["layerwrap-"+e])try{if(e=(layerObj["layerwrap-"+e]?"layerwrap-":"")+e,!layerObj[e].show)return;layerObj[e].parentElem.replaceChild(layerObj[e].wrap,layerDom[e][0]),layerObj[e].wrap.style.display="none",layerObj[e].show=!1}catch(e){}else{unique=null;try{layerDom[e][0].classList.add("shift"),layerDom[e][1].classList.add("shift"),layerDom[e][0].style.opacity="",layerDom[e][1].style.opacity=0,setTimeout(function(){layerDom[e][0].parentNode.removeChild(layerDom[e][0]),delete layerDom[e],delete Anot.vmodels[e]},200)}catch(e){}}document.body.style.overflow=""},repeat=function(e,t){let o=0,s="";for(;o{this.$refs.layer.classList.remove("scale")},100)},onMaskClick:function(){this.type<4&&!this.maskClose?this.shake():this.maskClose&&this.close()},handleConfirm:function(){if(3===this.type&&!this.prompt)return this.shake();if("function"==typeof this.props.yes){let e=[this.$id];3===this.type&&e.unshift(this.prompt),this.props.yes.apply(this,e)}else this.close()},handleCancel:function(){"function"==typeof this.props.no?this.props.no.call(this,this.$id):this.close()},close:function(){close(this.$id)},cancelBubble:function(e){e.cancelBubble=!0}},mounted:function(){"function"==typeof this.props.success&&this.props.success.call(this)}},4===this.init.state.type&&(this.init.methods.autoSize=function(){let{layer:e,frame:t}=this.$refs;t.onload=function(){setTimeout(function(){try{let o=t.contentWindow.document.body,{clientWidth:s,clientHeight:n}=o;Anot(e).css({width:s,height:n,marginLeft:-s/2,marginTop:-n/2}),Anot(t).css({height:n})}catch(e){}},500)}}),this}create(){let{state:e,$id:t}=this.init,o=document.createElement("div"),s=document.createElement("div");if(o.setAttribute("anot",t),o.setAttribute(":click","onMaskClick"),o.classList.add("do-layer"),e.mask&&(o.classList.add("mask"),e.container&&e.container!==document.body&&o.classList.add("inner")),e.maskColor&&(o.style.background=e.maskColor),s.classList.add("layer-box"),s.classList.add("skin-normal"),e.extraClass&&(s.classList.add(e.extraClass),delete e.extraClass),"string"==typeof e.shift)s.classList.add("__"+e.shift);else for(let t in e.shift){let o=e.shift[t];o+=isFinite(o)?"px":"",s.style.cssText+=`${t}: ${o};`}e.toast?s.classList.add("type-toast"):s.classList.add("type-"+e.type),s.setAttribute("ref","layer"),s.setAttribute(":click","cancelBubble"),s.style.cssText+="border-radius:"+e.radius+"px",e.menubar||e.fixed||(s.setAttribute(":drag",""),s.setAttribute("data-limit","window"));var n="";"auto"!==e.area[0]&&(n+="width: "+e.area[0]+";"),"auto"!==e.area[1]&&(n+="height: "+e.area[1]+";");let i="";return 5===e.type&&(i+=''),s.innerHTML=`\n ${this.mkMenubar()}\n \n\n ${6===e.type?this.mkLoading(e.load):""}\n \n ${this.mkCtrl()}\n ${i}\n `,delete e.wrap,o.appendChild(s),[o,s]}mkLoading(e){return`\n
\n \n ${repeat(1===e?'':"",this.dot[e])}\n \n
\n `}mkMenubar(){let{menubar:e,fixed:t}=this.init.state,o="";return e&&(o=`\n
\n
\n `),o}mkCtrl(){let{type:e}=this.init.state;if(e>3)return"";{let t="",o='\n \n ';return e>1&&(o='\n \n '+o),t=`\n
\n ${o}\n
\n `}}append(){let{state:e,$id:t}=this.init,o=e.container;return e.type<4&&(unique&&close(unique),unique=t),layerDom[t]=this.create(),delete e.toast,this.toast=!0,o||(o=document.body),o.appendChild(layerDom[t][0]),this.vm=Anot(this.init),this}show(){let{state:e,$id:t}=this.init,o=(this.vm,e.container);setTimeout(function(){let s={background:e.background},n=getComputedStyle(layerDom[t][1]);if(5===e.type){s.color=e.color,s.opacity=1;let i=Anot(o),a=i[0].querySelector(".arrow"),r=i.innerWidth(),l=i.innerHeight(),c=i.offset().left-$doc.scrollLeft(),d=i.offset().top-$doc.scrollTop(),p=parseInt(n.width),f=parseInt(n.height),y=["top"];Anot(layerDom[t][1]).css(s),i.bind("mouseenter",o=>{let s={visibility:"visible"};c=i.offset().left-$doc.scrollLeft(),(d=i.offset().top-$doc.scrollTop())+18window.innerWidth?(s.left=c+.3*r-p,y[1]="left"):s.left=c+.7*r,a.classList.add("offset-"+y.join("-")),Anot(layerDom[t][1]).css(s)}),i.bind("mouseleave",()=>{setTimeout(()=>{a.classList.remove("offset-"+y.join("-")),y=["top"],a.style.borderBottomColor="",a.style.borderTopColor="",layerDom[t][1].style.visibility="hidden"},100)})}else{let o={opacity:1};e.offset?(o.top=fixOffset(e.offset[0]),o.right=fixOffset(e.offset[1]),o.bottom=fixOffset(e.offset[2]),o.left=fixOffset(e.offset[3]),"auto"===o.left&&"auto"===o.right&&(o.left="50%",s.marginLeft=-parseInt(n.width)/2),"auto"===o.top&&"auto"===o.bottom&&(o.top="50%",s.marginTop=-parseInt(n.height)/2)):s=Object.assign(s,{marginLeft:-parseInt(n.width)/2,marginTop:-parseInt(n.height)/2}),Anot(layerDom[t][1]).css(s),setTimeout(()=>{document.body.style.overflow="hidden",layerDom[t][1].classList.add("shift"),setTimeout(s=>{Anot(layerDom[t][1]).css(o),setTimeout(o=>{try{layerDom[t][1].classList.remove("shift"),layerDom[t][1].classList.remove("__"+e.shift)}catch(e){}},500)},50)},50)}},4),e.type>3&&(e.timeout>0?(clearTimeout(this.timeout),this.timeout=setTimeout(()=>{clearTimeout(this.timeout),close(t),6===e.type&&this.vm.props.yes.call(this.vm,t)},e.timeout)):6===e.type&&this.vm.props.yes.call(this.vm,t))}}const _layer={alert(e,t,o){let s={content:e,fixed:!0};return"function"==typeof t?s.yes=t:(t&&(s.title=t+""),o&&"function"==typeof o&&(s.yes=o)),_layer.open(s)},confirm(e,t,o,s){let n={content:e,fixed:!0,type:2};return"function"==typeof t?(n.yes=t,"function"==typeof o&&(n.no=o)):(t&&(n.title=t+""),o&&"function"==typeof o&&(n.yes=o),s&&"function"==typeof s&&(n.no=s)),_layer.open(n)},frame(e,t={}){let o={content:``,menubar:!1,maskClose:!0,type:4,...t};return _layer.open(o)},toast(e,t="info",o=2500){switch("number"==typeof t&&(o=t,t="info"),t){case"info":case"warn":break;case"error":t="deny";break;default:t="info"}let s={content:`\n \n \n ${e}\n `,menubar:!1,mask:!1,type:7,shift:"tc",timeout:o,offset:[50,"auto"],fixed:!0,toast:!0};return _layer.open(s)},load:(e,t,o)=>(e=(e>>>=0)<1?1:e>4?4:e,"function"==typeof t?(o=t,t=null):(t instanceof HTMLElement||(t=null),"function"!=typeof o&&(o=Anot.noop)),_layer.open({container:t,type:6,load:e,yes:o,menubar:!1,background:"none",shift:"ct",fixed:!0})),tips:(e,t,o={})=>t instanceof HTMLElement?(o.background||(o.background="rgba(0,0,0,.5)"),o.color||(o.color="#fff"),Object.assign(o,{container:t,content:e,type:5,fixed:!0,mask:!1,menubar:!1,timeout:0}),_layer.open(o)):Anot.error(lang.NEED_CONTAINER),prompt(e,t){if("function"!=typeof t)return console.error("argument [callback] requires a function, but "+typeof t+" given");let o={type:3,prompt:"",title:e,content:'',fixed:!0,yes:t};return _layer.open(o)},close:close,open(e){if("string"==typeof e){if(layerObj[e="layerwrap-"+e])return layerObj[e].show?e:(layerObj[e].show=!0,layerObj[e].parentElem.appendChild(layerDom[e][0]),layerDom[e][0].querySelector(".layer-content").appendChild(layerObj[e].wrap),layerObj[e].wrap.style.display="",Anot.vmodels[e]||Anot(layerObj[e].obj.init),layerObj[e].obj.show(),e);throw new Error(lang.ERROR)}return new __layer__(e).init.$id},version:Anot.ui.layer};Anot.directive("layer",{priority:8090,init:function(e){e.element.removeAttribute(e.name),e.param&&"tips"===e.param||(e.param="",e.element.style.display="none")},update:function(e){if(!e)return console.error(this),console.error(`SyntaxError: Unexpected [${this.name}=${this.expr}]`);let t=Object.assign({type:7,wrap:!0},this.element.dataset);if(this.param){if("tips"===this.param){let o=document.createElement("div"),s=document.createElement("span"),n=document.createElement("i");o.className="do-layer__tips",s.className="layer-content",n.className="arrow",s.textContent=e,o.appendChild(s),o.appendChild(n),this.element.appendChild(o),t.color&&(i.color=t.color),t.color&&(i.background=t.background);let i={},a=getComputedStyle(o),r=Anot(this.element),l=r.innerWidth(),c=r.innerHeight(),d=r.offset().left-$doc.scrollLeft(),p=r.offset().top-$doc.scrollTop(),f=parseInt(a.width),y=parseInt(a.height),u=["top"];Anot(o).css(i),r.bind("mouseenter",e=>{let s={visibility:"visible"};d=r.offset().left-$doc.scrollLeft(),(p=r.offset().top-$doc.scrollTop())+18window.innerWidth?(s.left=d+.3*l-f,u[1]="left"):s.left=d+.7*l,n.classList.add("offset-"+u.join("-")),Anot(o).css(s)}),r.bind("mouseleave",()=>{setTimeout(()=>{n.classList.remove("offset-"+u.join("-")),u=["top"],n.style.borderBottomColor="",n.style.borderTopColor="",o.style.visibility="hidden"},100)})}}else{let o={$id:"layerwrap-"+e,state:t,props:{}};t.hasOwnProperty("area")&&(t.area=t.area.split(",")),t.hasOwnProperty("offset")&&(t.offset=t.offset.split(",")),t.hasOwnProperty("btns")&&(t.btns=t.btns.split(",")),t.hasOwnProperty("menubar")||(t.menubar=!1);let s=(new __layer__).__init__(o);for(let e in this.element.dataset)delete this.element.dataset[e];layerObj[s.init.$id]={obj:s,parentElem:this.element.parentNode,wrap:this.element,show:!1},layerDom[s.init.$id]=s.create()}}}),window.layer=_layer;export default _layer; \ No newline at end of file diff --git a/src/lib/lyrics/index.js b/src/lib/lyrics/index.js index a92b9c0..fa70d78 100644 --- a/src/lib/lyrics/index.js +++ b/src/lib/lyrics/index.js @@ -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) } diff --git a/src/lib/store/index.js b/src/lib/store/index.js index 32bf94a..e4ccb68 100644 --- a/src/lib/store/index.js +++ b/src/lib/store/index.js @@ -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; \ No newline at end of file +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; \ No newline at end of file diff --git a/src/main.js b/src/main.js index a0de521..98c5cb8 100644 --- a/src/main.js +++ b/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() - } -}) diff --git a/src/tools/init.js b/src/tools/init.js new file mode 100644 index 0000000..63d9b8c --- /dev/null +++ b/src/tools/init.js @@ -0,0 +1,117 @@ +/** + * 配置/DB通讯 + * @author yutent + * @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 + } +}) diff --git a/src/tools/windows.js b/src/tools/windows.js new file mode 100644 index 0000000..280289d --- /dev/null +++ b/src/tools/windows.js @@ -0,0 +1,106 @@ +/** + * 各种窗口创建 + * @author yutent + * @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 +}