feat: update electron app with touchbar and menu.
6
.npmrc
|
@ -1,4 +1,4 @@
|
||||||
# 如果发现 npm / yarn 安装太慢,可以解除注释
|
# 如果发现 npm / yarn 安装太慢,可以解除注释
|
||||||
registry=https://registry.npm.taobao.org/
|
# registry=https://registry.npm.taobao.org/
|
||||||
ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron
|
# ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron
|
||||||
phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs
|
# phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs
|
|
@ -56,8 +56,7 @@
|
||||||
"vue-i18n": "^8.22.0",
|
"vue-i18n": "^8.22.0",
|
||||||
"vue-router": "^3.4.3",
|
"vue-router": "^3.4.3",
|
||||||
"vue-slider-component": "^3.2.5",
|
"vue-slider-component": "^3.2.5",
|
||||||
"vuex": "^3.4.0",
|
"vuex": "^3.4.0"
|
||||||
"vuex-electron": "^1.0.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sentry/browser": "^5.27.0",
|
"@sentry/browser": "^5.27.0",
|
||||||
|
|
BIN
public/img/icons/touchbar/like.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/icons/touchbar/liked.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/icons/touchbar/next.png
Normal file
After Width: | Height: | Size: 1005 B |
BIN
public/img/icons/touchbar/play.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/icons/touchbar/previous.png
Normal file
After Width: | Height: | Size: 1021 B |
BIN
public/img/icons/touchbar/repeat.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
public/img/icons/touchbar/search.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/img/icons/touchbar/search2.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/img/icons/touchbar/shuffle.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
35
src/App.vue
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<Navbar />
|
<Navbar ref="navbar"/>
|
||||||
<main>
|
<main>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view v-if="$route.meta.keepAlive"></router-view>
|
<router-view v-if="$route.meta.keepAlive"></router-view>
|
||||||
|
@ -40,6 +40,7 @@ export default {
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.isElectron) {
|
if (this.isElectron) {
|
||||||
|
const self = this
|
||||||
// 添加专有的类名
|
// 添加专有的类名
|
||||||
document.body.classList.add("is-electron");
|
document.body.classList.add("is-electron");
|
||||||
// ipc message channel
|
// ipc message channel
|
||||||
|
@ -49,38 +50,42 @@ export default {
|
||||||
// inside this Vue instance, according to what path the main process requires.
|
// inside this Vue instance, according to what path the main process requires.
|
||||||
// responds to Menu click() events at the main process and changes the route accordingly.
|
// responds to Menu click() events at the main process and changes the route accordingly.
|
||||||
ipcRenderer.on("changeRouteTo", (event, path) => {
|
ipcRenderer.on("changeRouteTo", (event, path) => {
|
||||||
console.log(event);
|
self.$router.push(path);
|
||||||
this.$router.push(path);
|
|
||||||
});
|
});
|
||||||
|
ipcRenderer.on("search", () => {
|
||||||
|
// 触发数据响应
|
||||||
|
self.$refs.navbar.$refs.searchInput.focus()
|
||||||
|
self.$refs.navbar.inputFocus = true
|
||||||
|
})
|
||||||
ipcRenderer.on("play", () => {
|
ipcRenderer.on("play", () => {
|
||||||
this.$refs.player.play();
|
self.$refs.player.play();
|
||||||
});
|
});
|
||||||
ipcRenderer.on("next", () => {
|
ipcRenderer.on("next", () => {
|
||||||
this.$refs.player.next();
|
self.$refs.player.next();
|
||||||
});
|
});
|
||||||
ipcRenderer.on("previous", () => {
|
ipcRenderer.on("previous", () => {
|
||||||
this.$refs.player.previous();
|
self.$refs.player.previous();
|
||||||
});
|
});
|
||||||
ipcRenderer.on("increaseVolume", () => {
|
ipcRenderer.on("increaseVolume", () => {
|
||||||
if (this.$refs.player.volume + 0.1 >= 1) {
|
if (self.$refs.player.volume + 0.1 >= 1) {
|
||||||
return (this.$refs.player.volume = 1);
|
return (self.$refs.player.volume = 1);
|
||||||
}
|
}
|
||||||
this.$refs.player.volume += 0.1;
|
self.$refs.player.volume += 0.1;
|
||||||
});
|
});
|
||||||
ipcRenderer.on("decreaseVolume", () => {
|
ipcRenderer.on("decreaseVolume", () => {
|
||||||
if (this.$refs.player.volume - 0.1 <= 0) {
|
if (self.$refs.player.volume - 0.1 <= 0) {
|
||||||
return (this.$refs.player.volume = 0);
|
return (self.$refs.player.volume = 0);
|
||||||
}
|
}
|
||||||
this.$refs.player.volume -= 0.1;
|
self.$refs.player.volume -= 0.1;
|
||||||
});
|
});
|
||||||
ipcRenderer.on("like", () => {
|
ipcRenderer.on("like", () => {
|
||||||
this.$refs.player.likeCurrentSong();
|
self.$refs.player.likeCurrentSong();
|
||||||
});
|
});
|
||||||
ipcRenderer.on("repeat", () => {
|
ipcRenderer.on("repeat", () => {
|
||||||
this.$refs.player.repeat();
|
self.$refs.player.repeat();
|
||||||
});
|
});
|
||||||
ipcRenderer.on("shuffle", () => {
|
ipcRenderer.on("shuffle", () => {
|
||||||
this.$refs.player.shuffle();
|
self.$refs.player.shuffle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,48 +1,59 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
const path = require('path')
|
||||||
import path from "path";
|
|
||||||
// import { autoUpdater } from "electron-updater"
|
// import { autoUpdater } from "electron-updater"
|
||||||
import {
|
import {
|
||||||
app,
|
app,
|
||||||
protocol,
|
protocol,
|
||||||
BrowserWindow,
|
BrowserWindow,
|
||||||
ipcMain,
|
ipcMain,
|
||||||
dialog,
|
globalShortcut
|
||||||
globalShortcut,
|
|
||||||
} from "electron";
|
} from "electron";
|
||||||
|
|
||||||
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
|
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
|
||||||
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
|
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
|
||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== "production";
|
const isDevelopment = process.env.NODE_ENV !== "production";
|
||||||
|
const { createTouchBar } = require("./electron/touchbar");
|
||||||
|
const { createMenu } = require("./electron/menu");
|
||||||
|
const { setAppBounced } = require("./electron/bounced")
|
||||||
|
const { setIcon } = require("./electron/setIcon")
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
// Keep a global reference of the window object, if you don't, the window will
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
// be closed automatically when the JavaScript object is garbage collected.
|
||||||
let win;
|
let win;
|
||||||
|
let touchbar
|
||||||
|
|
||||||
|
const iconString = path.join(__static, "img/icons/apple-touch-icon.png");
|
||||||
|
|
||||||
|
// Make vuex copy for electron.
|
||||||
|
global.vuexCopy = null
|
||||||
|
// 同步 vuex 状态,由于 player 有循环引用问题,拷贝部分属性
|
||||||
|
ipcMain.on('vuex-state', (e, state) => {
|
||||||
|
global.vuexCopy = state
|
||||||
|
})
|
||||||
|
ipcMain.on("close", () => {
|
||||||
|
win.close();
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
ipcMain.on("minimize", () => {
|
||||||
|
win.minimize();
|
||||||
|
});
|
||||||
|
|
||||||
// Scheme must be registered before the app is ready
|
// Scheme must be registered before the app is ready
|
||||||
protocol.registerSchemesAsPrivileged([
|
protocol.registerSchemesAsPrivileged([
|
||||||
{ scheme: "app", privileges: { secure: true, standard: true } },
|
{ scheme: "app", privileges: { secure: true, standard: true } },
|
||||||
]);
|
]);
|
||||||
const iconString = path.join(__static, "img/icons/apple-touch-icon.png");
|
|
||||||
|
|
||||||
let bounceId = app.dock.bounce();
|
setAppBounced(app)
|
||||||
app.dock.setIcon(iconString);
|
setIcon(app, iconString)
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
const touchbar = require("./electron/touchbar.js");
|
|
||||||
const tray = require("./electron/tray.js");
|
const tray = require("./electron/tray.js");
|
||||||
const createMenu = require("./electron/menu.js");
|
|
||||||
tray.on("click", function () {
|
|
||||||
if (win.isVisible()) {
|
|
||||||
win.hide();
|
|
||||||
} else {
|
|
||||||
win.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
win = new BrowserWindow({
|
win = new BrowserWindow({
|
||||||
width: 1440,
|
width: 1440,
|
||||||
height: 768,
|
height: 768,
|
||||||
icon: iconString,
|
icon: iconString,
|
||||||
|
backgroundColor: '#2e2c29',
|
||||||
titleBarStyle: "default",
|
titleBarStyle: "default",
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
webSecurity: false,
|
webSecurity: false,
|
||||||
|
@ -51,15 +62,13 @@ function createWindow() {
|
||||||
preload: path.join(__dirname, "./electron/preload.js"),
|
preload: path.join(__dirname, "./electron/preload.js"),
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
tray.on("click", () => {
|
||||||
createMenu(win);
|
if (win && win.isVisible()) {
|
||||||
win.setTouchBar(touchbar);
|
win.hide();
|
||||||
win.setAutoHideCursor(true);
|
} else {
|
||||||
app.dock.cancelBounce(bounceId);
|
win.show();
|
||||||
// autoUpdater.checkForUpdatesAndNotify()
|
}
|
||||||
} catch (error) {
|
});
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||||
// Load the url of the dev server if in development mode
|
// Load the url of the dev server if in development mode
|
||||||
|
@ -74,6 +83,7 @@ function createWindow() {
|
||||||
win.on("closed", () => {
|
win.on("closed", () => {
|
||||||
win = null;
|
win = null;
|
||||||
});
|
});
|
||||||
|
return win
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
// Quit when all windows are closed.
|
||||||
|
@ -112,14 +122,13 @@ app.on("ready", async () => {
|
||||||
win.webContents.openDevTools();
|
win.webContents.openDevTools();
|
||||||
});
|
});
|
||||||
createWindow();
|
createWindow();
|
||||||
});
|
win.once("ready-to-show", () => {
|
||||||
|
win.show()
|
||||||
ipcMain.on("close", () => {
|
})
|
||||||
win.close();
|
createMenu(win);
|
||||||
app.quit();
|
touchbar = createTouchBar(win)
|
||||||
});
|
win.setTouchBar(touchbar);
|
||||||
ipcMain.on("minimize", () => {
|
// autoUpdater.checkForUpdatesAndNotify()
|
||||||
win.minimize();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// autoUpdater.on("checking-for-update", () => {});
|
// autoUpdater.on("checking-for-update", () => {});
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<svg-icon icon-class="search" />
|
<svg-icon icon-class="search" />
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input
|
<input
|
||||||
|
ref="searchInput"
|
||||||
:placeholder="inputFocus ? '' : $t('nav.search')"
|
:placeholder="inputFocus ? '' : $t('nav.search')"
|
||||||
v-model="keywords"
|
v-model="keywords"
|
||||||
@keydown.enter="goToSearchPage"
|
@keydown.enter="goToSearchPage"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<div class="playing">
|
<div class="playing">
|
||||||
<img
|
<img
|
||||||
:src="currentTrack.al.picUrl | resizeImage(224)"
|
:src="currentTrack.al && currentTrack.al.picUrl | resizeImage(224)"
|
||||||
@click="goToAlbum"
|
@click="goToAlbum"
|
||||||
/>
|
/>
|
||||||
<div class="track-info">
|
<div class="track-info">
|
||||||
|
@ -141,9 +141,12 @@ export default {
|
||||||
oldVolume: 0.5,
|
oldVolume: 0.5,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
mounted() {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.progress = ~~this.howler.seek();
|
// fix 歌曲播放完还设置进度的问题,及 _id 不存在的问题
|
||||||
|
if (this.howler && this.howler._sounds[0]._id) {
|
||||||
|
this.progress = ~~this.howler.seek();
|
||||||
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
if (isAccountLoggedIn()) {
|
if (isAccountLoggedIn()) {
|
||||||
userLikedSongsIDs(this.data.user.userId).then((data) => {
|
userLikedSongsIDs(this.data.user.userId).then((data) => {
|
||||||
|
@ -167,9 +170,12 @@ export default {
|
||||||
},
|
},
|
||||||
playing() {
|
playing() {
|
||||||
if (this.howler.state() === "loading") {
|
if (this.howler.state() === "loading") {
|
||||||
|
this.updatePlayerState({ key: "playing", value: true });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.howler.playing();
|
const status = this.howler.playing()
|
||||||
|
this.updatePlayerState({ key: "playing", value: status });
|
||||||
|
return status
|
||||||
},
|
},
|
||||||
progressMax() {
|
progressMax() {
|
||||||
let max = ~~(this.currentTrack.dt / 1000);
|
let max = ~~(this.currentTrack.dt / 1000);
|
||||||
|
|
6
src/electron/bounced.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export function setAppBounced(app) {
|
||||||
|
let bounceId = app.dock.bounce();
|
||||||
|
app.on('ready', () => {
|
||||||
|
app.dock.cancelBounce(bounceId);
|
||||||
|
})
|
||||||
|
};
|
|
@ -4,7 +4,7 @@ const { app, Menu } = require("electron");
|
||||||
|
|
||||||
const isMac = process.platform === "darwin";
|
const isMac = process.platform === "darwin";
|
||||||
|
|
||||||
function createMenu(win) {
|
export function createMenu(win) {
|
||||||
let menu = null;
|
let menu = null;
|
||||||
const template = [
|
const template = [
|
||||||
...(isMac
|
...(isMac
|
||||||
|
@ -196,5 +196,3 @@ function createMenu(win) {
|
||||||
menu = Menu.buildFromTemplate(template);
|
menu = Menu.buildFromTemplate(template);
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = createMenu;
|
|
||||||
|
|
3
src/electron/setIcon.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export function setIcon(app, iconString) {
|
||||||
|
app.dock.setIcon(iconString);
|
||||||
|
}
|
|
@ -1,104 +1,131 @@
|
||||||
// 运用 ipdMain 请求用户喜欢的歌手的数据,随机抽几个歌手进行随机
|
const { TouchBar, nativeImage, ipcMain } = require("electron");
|
||||||
const { TouchBar } = require("electron");
|
const path = require("path");
|
||||||
|
|
||||||
const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar;
|
const {
|
||||||
|
TouchBarButton,
|
||||||
|
TouchBarGroup,
|
||||||
|
TouchBarSpacer,
|
||||||
|
TouchBarSegmentedControl,
|
||||||
|
} = TouchBar;
|
||||||
|
|
||||||
let spinning = false;
|
function getNativeIcon(name, width = 24, height = 24) {
|
||||||
|
return nativeImage
|
||||||
|
.createFromPath(path.join(__static, "img/icons/touchbar/", name))
|
||||||
|
.resize({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Reel labels
|
export function createSegmentedControl(renderer) {
|
||||||
const reel1 = new TouchBarLabel();
|
const segments = [
|
||||||
const reel2 = new TouchBarLabel();
|
{
|
||||||
const reel3 = new TouchBarLabel();
|
icon: getNativeIcon("previous.png"),
|
||||||
|
},
|
||||||
// Spin result label
|
{
|
||||||
const result = new TouchBarLabel();
|
icon: getNativeIcon("play.png", 20, 20),
|
||||||
|
},
|
||||||
// Spin button
|
{
|
||||||
const spin = new TouchBarButton({
|
icon: getNativeIcon("next.png"),
|
||||||
label: "🎰 Spin",
|
},
|
||||||
backgroundColor: "#7851A9",
|
];
|
||||||
click: () => {
|
const segmentedControl = new TouchBarSegmentedControl({
|
||||||
// Ignore clicks if already spinning
|
segments,
|
||||||
if (spinning) {
|
change: (selectedIndex) => {
|
||||||
return;
|
const temp = Object.assign([], segmentedControl.segments);
|
||||||
}
|
if (selectedIndex === 0) {
|
||||||
|
renderer.send("previous");
|
||||||
spinning = true;
|
|
||||||
result.label = "";
|
|
||||||
|
|
||||||
let timeout = 10;
|
|
||||||
const spinLength = 4 * 1000; // 4 seconds
|
|
||||||
const startTime = Date.now();
|
|
||||||
|
|
||||||
const spinReels = () => {
|
|
||||||
updateReels();
|
|
||||||
|
|
||||||
if (Date.now() - startTime >= spinLength) {
|
|
||||||
finishSpin();
|
|
||||||
} else {
|
|
||||||
// Slow down a bit on each spin
|
|
||||||
timeout *= 1.1;
|
|
||||||
setTimeout(spinReels, timeout);
|
|
||||||
}
|
}
|
||||||
};
|
if (selectedIndex === 1) {
|
||||||
|
ipcMain.on("vuex-state", (e, { player }) => {
|
||||||
|
const playing = player.playing;
|
||||||
|
if (playing === true) {
|
||||||
|
// To be paused
|
||||||
|
temp[1].icon = getNativeIcon("play.png", 20, 20);
|
||||||
|
segmentedControl.segments = temp;
|
||||||
|
} else {
|
||||||
|
temp[1].icon = getNativeIcon("play.png", 20, 20);
|
||||||
|
segmentedControl.segments = temp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
renderer.send("play");
|
||||||
|
}
|
||||||
|
if (selectedIndex === 2) {
|
||||||
|
renderer.send("next");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mode: "buttons",
|
||||||
|
});
|
||||||
|
return segmentedControl;
|
||||||
|
}
|
||||||
|
|
||||||
spinReels();
|
export function createPreferGroup(renderer) {
|
||||||
},
|
const search = new TouchBarButton({
|
||||||
});
|
icon: getNativeIcon("search.png", 22, 22),
|
||||||
|
click: () => {
|
||||||
|
renderer.send("search");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const like = new TouchBarButton({
|
||||||
|
icon: getNativeIcon("like.png"),
|
||||||
|
click: () => {
|
||||||
|
ipcMain.on("vuex-state", (e, { liked, player }) => {
|
||||||
|
const currentTrack = player.currentTrack;
|
||||||
|
if (liked.songs.includes(currentTrack.id)) {
|
||||||
|
like.icon = getNativeIcon("liked.png");
|
||||||
|
} else {
|
||||||
|
like.icon = getNativeIcon("like.png");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
renderer.send("like");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const repeat = new TouchBarButton({
|
||||||
|
icon: getNativeIcon("repeat.png"),
|
||||||
|
click: () => {
|
||||||
|
ipcMain.on("vuex-state", (e, { player }) => {
|
||||||
|
const repeat = player.repeat;
|
||||||
|
if (repeat === "on") {
|
||||||
|
repeat.icon = getNativeIcon("repeat.png");
|
||||||
|
} else if (repeat === "one") {
|
||||||
|
repeat.icon = getNativeIcon("repeat.png");
|
||||||
|
} else {
|
||||||
|
repeat.icon = getNativeIcon("repeat.png");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
renderer.send("repeat");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const shuffle = new TouchBarButton({
|
||||||
|
icon: getNativeIcon("shuffle.png"),
|
||||||
|
click: () => {
|
||||||
|
ipcMain.on("vuex-state", (e, { player }) => {
|
||||||
|
const shuffle = player.shuffle;
|
||||||
|
if (shuffle === true) {
|
||||||
|
shuffle.icon = getNativeIcon("shuffle.png");
|
||||||
|
} else {
|
||||||
|
shuffle.icon = getNativeIcon("shuffle.png");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
renderer.send("shuffle");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return new TouchBar({
|
||||||
|
items: [search, like, repeat, shuffle],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const getRandomValue = () => {
|
export function createTouchBar(window) {
|
||||||
const values = ["🍒", "💎", "7️⃣", "🍊", "🔔", "⭐", "🍇", "🍀"];
|
const renderer = window.webContents;
|
||||||
return values[Math.floor(Math.random() * values.length)];
|
const segmentedControl = createSegmentedControl(renderer);
|
||||||
};
|
const preferGroup = createPreferGroup(renderer);
|
||||||
|
const touchBar = new TouchBar({
|
||||||
const updateReels = () => {
|
items: [
|
||||||
reel1.label = getRandomValue();
|
new TouchBarGroup({ items: preferGroup }),
|
||||||
reel2.label = getRandomValue();
|
new TouchBarSpacer({ size: "large" }),
|
||||||
reel3.label = getRandomValue();
|
segmentedControl,
|
||||||
};
|
new TouchBarSpacer({ size: "large" }),
|
||||||
|
],
|
||||||
const finishSpin = () => {
|
});
|
||||||
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size;
|
return touchBar;
|
||||||
if (uniqueValues === 1) {
|
}
|
||||||
// All 3 values are the same
|
|
||||||
result.label = "💰 Jackpot!";
|
|
||||||
result.textColor = "#FDFF00";
|
|
||||||
} else if (uniqueValues === 2) {
|
|
||||||
// 2 values are the same
|
|
||||||
result.label = "😍 Winner!";
|
|
||||||
result.textColor = "#FDFF00";
|
|
||||||
} else {
|
|
||||||
// No values are the same
|
|
||||||
result.label = "🙁 Spin Again";
|
|
||||||
result.textColor = null;
|
|
||||||
}
|
|
||||||
spinning = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const touchBar = new TouchBar({
|
|
||||||
items: [
|
|
||||||
spin,
|
|
||||||
new TouchBarSpacer({ size: "large" }),
|
|
||||||
reel1,
|
|
||||||
new TouchBarSpacer({ size: "small" }),
|
|
||||||
reel2,
|
|
||||||
new TouchBarSpacer({ size: "small" }),
|
|
||||||
reel3,
|
|
||||||
new TouchBarSpacer({ size: "large" }),
|
|
||||||
result,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// let window
|
|
||||||
|
|
||||||
// app.whenReady().then(() => {
|
|
||||||
// window = new BrowserWindow({
|
|
||||||
// frame: false,
|
|
||||||
// titleBarStyle: 'hiddenInset',
|
|
||||||
// backgroundColor: '#000'
|
|
||||||
// })
|
|
||||||
// window.loadURL('about:blank')
|
|
||||||
// window.setTouchBar(touchBar)
|
|
||||||
// })
|
|
||||||
|
|
||||||
module.exports = touchBar;
|
|
||||||
|
|
104
src/electron/touchbar1.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// 运用 ipdMain 请求用户喜欢的歌手的数据,随机抽几个歌手进行随机
|
||||||
|
const { TouchBar } = require("electron");
|
||||||
|
|
||||||
|
const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar;
|
||||||
|
|
||||||
|
let spinning = false;
|
||||||
|
|
||||||
|
// Reel labels
|
||||||
|
const reel1 = new TouchBarLabel();
|
||||||
|
const reel2 = new TouchBarLabel();
|
||||||
|
const reel3 = new TouchBarLabel();
|
||||||
|
|
||||||
|
// Spin result label
|
||||||
|
const result = new TouchBarLabel();
|
||||||
|
|
||||||
|
// Spin button
|
||||||
|
const spin = new TouchBarButton({
|
||||||
|
label: "🎰 Spin",
|
||||||
|
backgroundColor: "#7851A9",
|
||||||
|
click: () => {
|
||||||
|
// Ignore clicks if already spinning
|
||||||
|
if (spinning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinning = true;
|
||||||
|
result.label = "";
|
||||||
|
|
||||||
|
let timeout = 10;
|
||||||
|
const spinLength = 4 * 1000; // 4 seconds
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
const spinReels = () => {
|
||||||
|
updateReels();
|
||||||
|
|
||||||
|
if (Date.now() - startTime >= spinLength) {
|
||||||
|
finishSpin();
|
||||||
|
} else {
|
||||||
|
// Slow down a bit on each spin
|
||||||
|
timeout *= 1.1;
|
||||||
|
setTimeout(spinReels, timeout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spinReels();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const getRandomValue = () => {
|
||||||
|
const values = ["🍒", "💎", "7️⃣", "🍊", "🔔", "⭐", "🍇", "🍀"];
|
||||||
|
return values[Math.floor(Math.random() * values.length)];
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateReels = () => {
|
||||||
|
reel1.label = getRandomValue();
|
||||||
|
reel2.label = getRandomValue();
|
||||||
|
reel3.label = getRandomValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
const finishSpin = () => {
|
||||||
|
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size;
|
||||||
|
if (uniqueValues === 1) {
|
||||||
|
// All 3 values are the same
|
||||||
|
result.label = "💰 Jackpot!";
|
||||||
|
result.textColor = "#FDFF00";
|
||||||
|
} else if (uniqueValues === 2) {
|
||||||
|
// 2 values are the same
|
||||||
|
result.label = "😍 Winner!";
|
||||||
|
result.textColor = "#FDFF00";
|
||||||
|
} else {
|
||||||
|
// No values are the same
|
||||||
|
result.label = "🙁 Spin Again";
|
||||||
|
result.textColor = null;
|
||||||
|
}
|
||||||
|
spinning = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const touchBar = new TouchBar({
|
||||||
|
items: [
|
||||||
|
spin,
|
||||||
|
new TouchBarSpacer({ size: "large" }),
|
||||||
|
reel1,
|
||||||
|
new TouchBarSpacer({ size: "small" }),
|
||||||
|
reel2,
|
||||||
|
new TouchBarSpacer({ size: "small" }),
|
||||||
|
reel3,
|
||||||
|
new TouchBarSpacer({ size: "large" }),
|
||||||
|
result,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// let window
|
||||||
|
|
||||||
|
// app.whenReady().then(() => {
|
||||||
|
// window = new BrowserWindow({
|
||||||
|
// frame: false,
|
||||||
|
// titleBarStyle: 'hiddenInset',
|
||||||
|
// backgroundColor: '#000'
|
||||||
|
// })
|
||||||
|
// window.loadURL('about:blank')
|
||||||
|
// window.setTouchBar(touchBar)
|
||||||
|
// })
|
||||||
|
|
||||||
|
module.exports = touchBar;
|
|
@ -1,12 +1,14 @@
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { Menu, Tray } = require("electron");
|
const { nativeImage, Tray } = require("electron");
|
||||||
|
|
||||||
let tray = null;
|
function getNativeIcon(name, width = 24, height = 24) {
|
||||||
|
return nativeImage.createFromPath(path.join(__static, 'img/icons/', name)).resize({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const macIcon = path.join(__static, "img/icons/menu.png");
|
let tray = new Tray(getNativeIcon('menu@88.png', 20, 20));;
|
||||||
const winIcon = path.join(__static, "img/icons/icon.ico");
|
|
||||||
|
|
||||||
tray = new Tray(macIcon);
|
|
||||||
|
|
||||||
// Temporary no need for menu.
|
// Temporary no need for menu.
|
||||||
// const contextMenu = Menu.buildFromTemplate([
|
// const contextMenu = Menu.buildFromTemplate([
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { getTrackDetail, scrobble } from "@/api/track";
|
||||||
import { isAccountLoggedIn } from "@/utils/auth";
|
import { isAccountLoggedIn } from "@/utils/auth";
|
||||||
// import { updateHttps } from "@/utils/common";
|
// import { updateHttps } from "@/utils/common";
|
||||||
import localforage from "localforage";
|
import localforage from "localforage";
|
||||||
import { cacheTrack } from "@/utils/db";
|
// import { cacheTrack } from "@/utils/db";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
switchTrack({ state, dispatch, commit }, basicTrack) {
|
switchTrack({ state, dispatch, commit }, basicTrack) {
|
||||||
|
@ -51,11 +51,13 @@ export default {
|
||||||
});
|
});
|
||||||
tracks.getItem(`${track.id}`).then((t) => {
|
tracks.getItem(`${track.id}`).then((t) => {
|
||||||
if (t !== null) {
|
if (t !== null) {
|
||||||
commitMP3(URL.createObjectURL(t.mp3));
|
// commitMP3(URL.createObjectURL(t.mp3));
|
||||||
|
commitMP3(t.mp3);
|
||||||
} else {
|
} else {
|
||||||
cacheTrack(`${track.id}`).then((t) => {
|
commitMP3(t.mp3);
|
||||||
commitMP3(URL.createObjectURL(t.mp3));
|
// cacheTrack(`${track.id}`).then((t) => {
|
||||||
});
|
// commitMP3(URL.createObjectURL(t.mp3));
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,42 +7,43 @@ import initLocalStorage from "./initLocalStorage";
|
||||||
import { Howl, Howler } from "howler";
|
import { Howl, Howler } from "howler";
|
||||||
import { changeAppearance } from "@/utils/common";
|
import { changeAppearance } from "@/utils/common";
|
||||||
import updateApp from "@/utils/updateApp";
|
import updateApp from "@/utils/updateApp";
|
||||||
import pack from "../../package.json";
|
import pkg from "../../package.json";
|
||||||
|
// vuex 自定义插件
|
||||||
|
import vuexBroadCast from './plugins/broadcast'
|
||||||
|
import saveToLocalStorage from './plugins/localStorage'
|
||||||
|
|
||||||
if (localStorage.getItem("appVersion") === null) {
|
if (localStorage.getItem("appVersion") === null) {
|
||||||
localStorage.setItem("player", JSON.stringify(initLocalStorage.player));
|
localStorage.setItem("player", JSON.stringify(initLocalStorage.player));
|
||||||
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
|
||||||
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
|
||||||
localStorage.setItem("appVersion", pack.version);
|
localStorage.setItem("appVersion", pkg.version);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateApp();
|
updateApp();
|
||||||
|
|
||||||
const saveToLocalStorage = (store) => {
|
|
||||||
store.subscribe((mutation, state) => {
|
|
||||||
// console.log(mutation);
|
|
||||||
localStorage.setItem("player", JSON.stringify(state.player));
|
|
||||||
localStorage.setItem("settings", JSON.stringify(state.settings));
|
|
||||||
localStorage.setItem("data", JSON.stringify(state.data));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
const store = new Vuex.Store({
|
|
||||||
state: state,
|
const options = {
|
||||||
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions,
|
actions,
|
||||||
plugins: [saveToLocalStorage],
|
plugins: [
|
||||||
});
|
saveToLocalStorage,
|
||||||
|
vuexBroadCast,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = new Vuex.Store(options);
|
||||||
|
|
||||||
store.state.howler = new Howl({
|
store.state.howler = new Howl({
|
||||||
src: [
|
src: [
|
||||||
`https://music.163.com/song/media/outer/url?id=${store.state.player.currentTrack.id}`,
|
`https://music.163.com/song/media/outer/url?id=${store.state.player.currentTrack.id}`,
|
||||||
],
|
],
|
||||||
html5: true,
|
html5: true,
|
||||||
format: ["mp3"],
|
format: ["webm", "mp3"],
|
||||||
});
|
});
|
||||||
|
|
||||||
Howler.volume(store.state.player.volume);
|
Howler.volume(store.state.player.volume);
|
||||||
|
|
||||||
if ([undefined, null].includes(store.state.settings.lang)) {
|
if ([undefined, null].includes(store.state.settings.lang)) {
|
||||||
|
@ -53,6 +54,7 @@ if ([undefined, null].includes(store.state.settings.lang)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
changeAppearance(store.state.settings.appearance);
|
changeAppearance(store.state.settings.appearance);
|
||||||
|
|
||||||
window
|
window
|
||||||
.matchMedia("(prefers-color-scheme: dark)")
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
.addEventListener("change", () => {
|
.addEventListener("change", () => {
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
src: [mp3],
|
src: [mp3],
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
html5: true,
|
html5: true,
|
||||||
|
format: ["webm", "mp3"],
|
||||||
});
|
});
|
||||||
state.howler.play();
|
state.howler.play();
|
||||||
},
|
},
|
||||||
|
|
17
src/store/plugins/broadcast.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// const electron = import('electron')
|
||||||
|
const electron = window.require("electron");
|
||||||
|
const ipcRenderer = electron.ipcRenderer;
|
||||||
|
|
||||||
|
export default store => {
|
||||||
|
// 第一行初始化第一次的状态
|
||||||
|
ipcRenderer.send('vuex-state', store.state)
|
||||||
|
store.subscribe((mutation, { data = '', settings = '', player = {}, contextMenu = {}, liked = {} }) => {
|
||||||
|
const copyState = { data, settings, player, contextMenu, liked }
|
||||||
|
ipcRenderer.send('vuex-state', copyState)
|
||||||
|
})
|
||||||
|
store.subscribe((mutation, state) => {
|
||||||
|
if (mutation.type === 'updateData') {
|
||||||
|
ipcRenderer.send('updateData', state.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
8
src/store/plugins/localStorage.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export default (store) => {
|
||||||
|
store.subscribe((mutation, state) => {
|
||||||
|
// console.log(mutation);
|
||||||
|
localStorage.setItem("player", JSON.stringify(state.player));
|
||||||
|
localStorage.setItem("settings", JSON.stringify(state.settings));
|
||||||
|
localStorage.setItem("data", JSON.stringify(state.data));
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,11 +1,11 @@
|
||||||
import axios from "axios";
|
// import axios from "axios";
|
||||||
import localforage from "localforage";
|
import localforage from "localforage";
|
||||||
import { getMP3 } from "@/api/track";
|
import { getMP3 } from "@/api/track";
|
||||||
|
|
||||||
export function cacheTrack(id) {
|
export function cacheTrack(id) {
|
||||||
let tracks = localforage.createInstance({
|
// let tracks = localforage.createInstance({
|
||||||
name: "tracks",
|
// name: "tracks",
|
||||||
});
|
// });
|
||||||
|
|
||||||
// TODO: limit cache songs number
|
// TODO: limit cache songs number
|
||||||
// tracks.length().then(function (length) {
|
// tracks.length().then(function (length) {
|
||||||
|
@ -18,14 +18,15 @@ export function cacheTrack(id) {
|
||||||
|
|
||||||
// TODO: cache track details
|
// TODO: cache track details
|
||||||
return getMP3(id).then((data) => {
|
return getMP3(id).then((data) => {
|
||||||
return axios
|
// return axios
|
||||||
.get(data.data[0].url.replace(/^http:/, "https:"), {
|
// .get(data.data[0].url.replace(/^http:/, "https:"), {
|
||||||
responseType: "blob",
|
// responseType: "blob",
|
||||||
})
|
// })
|
||||||
.then((data) => {
|
// .then((data) => {
|
||||||
tracks.setItem(`${id}`, { mp3: data.data });
|
// tracks.setItem(`${id}`, { mp3: data.data });
|
||||||
return { mp3: data.data };
|
// return { mp3: data.data };
|
||||||
});
|
// });
|
||||||
|
return { mp3: data.data[0].url.replace(/^http:/, "https:")}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ module.exports = {
|
||||||
// window 的 icon 头标
|
// window 的 icon 头标
|
||||||
win: {
|
win: {
|
||||||
publisherName: 'Yes Play Music',
|
publisherName: 'Yes Play Music',
|
||||||
icon: 'public/img/icons/512x512.png',
|
icon: 'build/icons/icon.ico',
|
||||||
publish: [
|
publish: [
|
||||||
"github"
|
"github"
|
||||||
],
|
],
|
||||||
|
@ -89,7 +89,8 @@ module.exports = {
|
||||||
"AppImage",
|
"AppImage",
|
||||||
"tar.gz",
|
"tar.gz",
|
||||||
"deb"
|
"deb"
|
||||||
]
|
],
|
||||||
|
icon: "build/icons"
|
||||||
},
|
},
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"icon": "build/icons/icon.icns"
|
"icon": "build/icons/icon.icns"
|
||||||
|
|
106
yarn.lock
|
@ -3459,17 +3459,6 @@ concat-stream@^1.5.0, concat-stream@^1.6.2:
|
||||||
readable-stream "^2.2.2"
|
readable-stream "^2.2.2"
|
||||||
typedarray "^0.0.6"
|
typedarray "^0.0.6"
|
||||||
|
|
||||||
conf@^2.0.0:
|
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/conf/download/conf-2.2.0.tgz#ee282efafc1450b61e205372041ad7d866802d9a"
|
|
||||||
integrity sha1-7igu+vwUULYeIFNyBBrX2GaALZo=
|
|
||||||
dependencies:
|
|
||||||
dot-prop "^4.1.0"
|
|
||||||
env-paths "^1.0.0"
|
|
||||||
make-dir "^1.0.0"
|
|
||||||
pkg-up "^2.0.0"
|
|
||||||
write-file-atomic "^2.3.0"
|
|
||||||
|
|
||||||
config-chain@^1.1.11:
|
config-chain@^1.1.11:
|
||||||
version "1.1.12"
|
version "1.1.12"
|
||||||
resolved "https://registry.npm.taobao.org/config-chain/download/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
|
resolved "https://registry.npm.taobao.org/config-chain/download/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
|
||||||
|
@ -3979,11 +3968,6 @@ deepmerge@^1.5.2:
|
||||||
resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
|
resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
|
||||||
integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M=
|
integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M=
|
||||||
|
|
||||||
deepmerge@^2.1.1:
|
|
||||||
version "2.2.1"
|
|
||||||
resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
|
||||||
integrity sha1-XT/yKgHAD2RUBaL7wX0HeKGAEXA=
|
|
||||||
|
|
||||||
default-gateway@^4.2.0:
|
default-gateway@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
|
resolved "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
|
||||||
|
@ -4227,13 +4211,6 @@ domutils@^1.5.1, domutils@^1.7.0:
|
||||||
dom-serializer "0"
|
dom-serializer "0"
|
||||||
domelementtype "1"
|
domelementtype "1"
|
||||||
|
|
||||||
dot-prop@^4.1.0:
|
|
||||||
version "4.2.1"
|
|
||||||
resolved "https://registry.npm.taobao.org/dot-prop/download/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4"
|
|
||||||
integrity sha1-RYhBlKcfws2nHLtLzrOk3S9DO6Q=
|
|
||||||
dependencies:
|
|
||||||
is-obj "^1.0.0"
|
|
||||||
|
|
||||||
dot-prop@^5.2.0:
|
dot-prop@^5.2.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.npm.taobao.org/dot-prop/download/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
|
resolved "https://registry.npm.taobao.org/dot-prop/download/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
|
||||||
|
@ -4414,13 +4391,6 @@ electron-publish@22.9.1:
|
||||||
lazy-val "^1.0.4"
|
lazy-val "^1.0.4"
|
||||||
mime "^2.4.6"
|
mime "^2.4.6"
|
||||||
|
|
||||||
electron-store@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/electron-store/download/electron-store-2.0.0.tgz#1035cca2a95409d1f54c7466606345852450d64a"
|
|
||||||
integrity sha1-EDXMoqlUCdH1THRmYGNFhSRQ1ko=
|
|
||||||
dependencies:
|
|
||||||
conf "^2.0.0"
|
|
||||||
|
|
||||||
electron-to-chromium@^1.3.570:
|
electron-to-chromium@^1.3.570:
|
||||||
version "1.3.570"
|
version "1.3.570"
|
||||||
resolved "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f"
|
resolved "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f"
|
||||||
|
@ -4512,11 +4482,6 @@ entities@^2.0.0:
|
||||||
resolved "https://registry.npm.taobao.org/entities/download/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
resolved "https://registry.npm.taobao.org/entities/download/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
||||||
integrity sha1-XEh+V0Krk8Fau12iJ1m4WQ7AO38=
|
integrity sha1-XEh+V0Krk8Fau12iJ1m4WQ7AO38=
|
||||||
|
|
||||||
env-paths@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/env-paths/download/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
|
|
||||||
integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=
|
|
||||||
|
|
||||||
env-paths@^2.2.0:
|
env-paths@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.npm.taobao.org/env-paths/download/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43"
|
resolved "https://registry.npm.taobao.org/env-paths/download/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43"
|
||||||
|
@ -5187,13 +5152,6 @@ find-up@^1.0.0:
|
||||||
path-exists "^2.0.0"
|
path-exists "^2.0.0"
|
||||||
pinkie-promise "^2.0.0"
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
find-up@^2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
|
|
||||||
integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
|
|
||||||
dependencies:
|
|
||||||
locate-path "^2.0.0"
|
|
||||||
|
|
||||||
find-up@^3.0.0:
|
find-up@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
resolved "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
||||||
|
@ -6410,7 +6368,7 @@ is-number@^7.0.0:
|
||||||
resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
|
integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
|
||||||
|
|
||||||
is-obj@^1.0.0, is-obj@^1.0.1:
|
is-obj@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||||
|
@ -7024,14 +6982,6 @@ localforage@^1.9.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
lie "3.1.1"
|
lie "3.1.1"
|
||||||
|
|
||||||
locate-path@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
|
|
||||||
integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
|
|
||||||
dependencies:
|
|
||||||
p-locate "^2.0.0"
|
|
||||||
path-exists "^3.0.0"
|
|
||||||
|
|
||||||
locate-path@^3.0.0:
|
locate-path@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||||
|
@ -7168,13 +7118,6 @@ lru-cache@^6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
make-dir@^1.0.0:
|
|
||||||
version "1.3.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
|
|
||||||
integrity sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=
|
|
||||||
dependencies:
|
|
||||||
pify "^3.0.0"
|
|
||||||
|
|
||||||
make-dir@^2.0.0:
|
make-dir@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
||||||
|
@ -7963,13 +7906,6 @@ p-finally@^2.0.0:
|
||||||
resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561"
|
resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561"
|
||||||
integrity sha1-vW/KqcVZoJa2gIBvTWV7Pw8kBWE=
|
integrity sha1-vW/KqcVZoJa2gIBvTWV7Pw8kBWE=
|
||||||
|
|
||||||
p-limit@^1.1.0:
|
|
||||||
version "1.3.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
|
|
||||||
integrity sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=
|
|
||||||
dependencies:
|
|
||||||
p-try "^1.0.0"
|
|
||||||
|
|
||||||
p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.3.0:
|
p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1594559734248&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1594559734248&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||||
|
@ -7984,13 +7920,6 @@ p-limit@^3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
p-try "^2.0.0"
|
p-try "^2.0.0"
|
||||||
|
|
||||||
p-locate@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
|
|
||||||
integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
|
|
||||||
dependencies:
|
|
||||||
p-limit "^1.1.0"
|
|
||||||
|
|
||||||
p-locate@^3.0.0:
|
p-locate@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
|
resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
|
||||||
|
@ -8036,11 +7965,6 @@ p-retry@^3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
retry "^0.12.0"
|
retry "^0.12.0"
|
||||||
|
|
||||||
p-try@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
|
||||||
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
|
|
||||||
|
|
||||||
p-try@^2.0.0:
|
p-try@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
resolved "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||||
|
@ -8368,13 +8292,6 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up "^4.0.0"
|
find-up "^4.0.0"
|
||||||
|
|
||||||
pkg-up@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.npm.taobao.org/pkg-up/download/pkg-up-2.0.0.tgz?cache=0&sync_timestamp=1589682752621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-up%2Fdownload%2Fpkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
|
|
||||||
integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
|
|
||||||
dependencies:
|
|
||||||
find-up "^2.1.0"
|
|
||||||
|
|
||||||
please-upgrade-node@^3.2.0:
|
please-upgrade-node@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.npm.taobao.org/please-upgrade-node/download/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
resolved "https://registry.npm.taobao.org/please-upgrade-node/download/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
||||||
|
@ -11180,14 +11097,6 @@ vue@^2.6.11:
|
||||||
resolved "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600443052956&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
|
resolved "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1600443052956&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
|
||||||
integrity sha1-9evU+mvShpQD4pqJau1JBEVskSM=
|
integrity sha1-9evU+mvShpQD4pqJau1JBEVskSM=
|
||||||
|
|
||||||
vuex-electron@^1.0.3:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.npm.taobao.org/vuex-electron/download/vuex-electron-1.0.3.tgz#c8ce0fd06ed9d3beb8881bce39bf76c9fcdc5611"
|
|
||||||
integrity sha1-yM4P0G7Z0764iBvOOb92yfzcVhE=
|
|
||||||
dependencies:
|
|
||||||
deepmerge "^2.1.1"
|
|
||||||
electron-store "^2.0.0"
|
|
||||||
|
|
||||||
vuex@^3.4.0:
|
vuex@^3.4.0:
|
||||||
version "3.5.1"
|
version "3.5.1"
|
||||||
resolved "https://registry.npm.taobao.org/vuex/download/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
|
resolved "https://registry.npm.taobao.org/vuex/download/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
|
||||||
|
@ -11598,19 +11507,10 @@ wrappy@1:
|
||||||
resolved "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||||
|
|
||||||
write-file-atomic@^2.3.0:
|
|
||||||
version "2.4.3"
|
|
||||||
resolved "https://registry.npm.taobao.org/write-file-atomic/download/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
|
|
||||||
integrity sha1-H9Lprh3z51uNjDZ0Q8aS1MqB9IE=
|
|
||||||
dependencies:
|
|
||||||
graceful-fs "^4.1.11"
|
|
||||||
imurmurhash "^0.1.4"
|
|
||||||
signal-exit "^3.0.2"
|
|
||||||
|
|
||||||
write-file-atomic@^3.0.0:
|
write-file-atomic@^3.0.0:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.npm.taobao.org/write-file-atomic/download/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
|
resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
|
||||||
integrity sha1-Vr1cWlxwSBzRnFcb05q5ZaXeVug=
|
integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
is-typedarray "^1.0.0"
|
is-typedarray "^1.0.0"
|
||||||
|
|