mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 21:28:06 +00:00
feat: integrate api in electron app
This commit is contained in:
parent
bd29570e31
commit
74bf714c28
240 changed files with 21003 additions and 112 deletions
|
|
@ -1,12 +1,21 @@
|
|||
"use strict";
|
||||
const { exec } = require("child_process");
|
||||
// const fs = require('fs')
|
||||
import { app, protocol, BrowserWindow } from "electron";
|
||||
|
||||
import path from 'path'
|
||||
// import { autoUpdater } from "electron-updater"
|
||||
import {
|
||||
app,
|
||||
protocol,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
dialog,
|
||||
globalShortcut,
|
||||
} from "electron";
|
||||
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
|
||||
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
|
||||
const isDevelopment = process.env.NODE_ENV !== "production";
|
||||
|
||||
// maybe use for modify app menu
|
||||
// const contextMenu = require('electron-context-menu');
|
||||
// import contextMenu from 'electron-context-menu'
|
||||
const isDevelopment = process.env.NODE_ENV !== "production";
|
||||
|
||||
// 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.
|
||||
|
|
@ -18,36 +27,19 @@ protocol.registerSchemesAsPrivileged([
|
|||
]);
|
||||
|
||||
function createWindow() {
|
||||
console.log("Node Version: ", process.version);
|
||||
const napi = exec("npm run napi:run");
|
||||
let scriptOutput = "";
|
||||
napi.stdout.setEncoding('utf8');
|
||||
napi.stdout.on('data', (data) => {
|
||||
console.log('napi: ' + data);
|
||||
data = data.toString();
|
||||
scriptOutput += data + '\n';
|
||||
// TODO write file with stream
|
||||
// const log = fs.createWriteStream(__dirname, '/tmp/' + +new Date + '.log')
|
||||
// log.write(scriptOutput)
|
||||
});
|
||||
// napi.stdout.on('error', (err) => {
|
||||
// console.log('napi error: ' + err);
|
||||
// data = err.toString();
|
||||
// scriptOutput += data + '\n';
|
||||
// const log = fs.createWriteStream(__dirname, '/tmp/' + +new Date + 'error.log')
|
||||
// log.write(scriptOutput)
|
||||
// });
|
||||
require('./electron/services')
|
||||
|
||||
// Create the browser window.
|
||||
// Create the browser window.
|
||||
win = new BrowserWindow({
|
||||
width: 1920,
|
||||
width: 1153,
|
||||
height: 768,
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
// Use pluginOptions.nodeIntegration, leave this alone
|
||||
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
|
||||
nodeIntegration: true,
|
||||
},
|
||||
icon: path.join(__static, "./img/icons/android-chrome-512x512.png"),
|
||||
preload: path.join(__dirname, "./electron/preload.js"),
|
||||
});
|
||||
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
|
|
@ -58,7 +50,7 @@ function createWindow() {
|
|||
createProtocol("app");
|
||||
// Load the index.html when not in development
|
||||
win.loadURL("app://./index.html");
|
||||
win.webContents.openDevTools();
|
||||
// autoUpdater.checkForUpdatesAndNotify()
|
||||
}
|
||||
|
||||
win.on("closed", () => {
|
||||
|
|
@ -95,9 +87,38 @@ app.on("ready", async () => {
|
|||
console.error("Vue Devtools failed to install:", e.toString());
|
||||
}
|
||||
}
|
||||
// Register shortcut for debug
|
||||
globalShortcut.register("CommandOrControl+K", function () {
|
||||
win.webContents.openDevTools();
|
||||
});
|
||||
createWindow();
|
||||
});
|
||||
|
||||
ipcMain.on("close", () => {
|
||||
win.close();
|
||||
app.quit();
|
||||
});
|
||||
ipcMain.on("minimize", () => {
|
||||
win.minimize();
|
||||
});
|
||||
|
||||
// autoUpdater.on("checking-for-update", () => {});
|
||||
// autoUpdater.on("update-available", info => {
|
||||
// console.log(info);
|
||||
// dialog.showMessageBox({
|
||||
// title: "新版本发布",
|
||||
// message: "有新内容更新,稍后将重新为您安装",
|
||||
// buttons: ["确定"],
|
||||
// type: "info",
|
||||
// noLink: true
|
||||
// });
|
||||
// });
|
||||
|
||||
// autoUpdater.on("update-downloaded", info => {
|
||||
// console.log(info);
|
||||
// autoUpdater.quitAndInstall();
|
||||
// });
|
||||
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
if (process.platform === "win32") {
|
||||
|
|
@ -112,3 +133,19 @@ if (isDevelopment) {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the app is singleton.
|
||||
function initialize() {
|
||||
const shouldQuit = !app.requestSingleInstanceLock();
|
||||
if (shouldQuit) return app.quit();
|
||||
// loadComponent()
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册主线程文件里的所有js
|
||||
*/
|
||||
// function loadComponent () {
|
||||
// require('./electron/menu.js')
|
||||
// }
|
||||
|
||||
initialize();
|
||||
|
|
|
|||
116
src/electron/command.js
Normal file
116
src/electron/command.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
"use strict";
|
||||
|
||||
import { app, ipcMain, Menu, MenuItem, BrowserWindow, globalShortcut } from 'electron'
|
||||
|
||||
let loginWindow, senders;
|
||||
|
||||
function openWindow(url) {
|
||||
const win = new BrowserWindow({
|
||||
height: 500,
|
||||
width: 350,
|
||||
useContentSize: true,
|
||||
transparent: false,
|
||||
frame: false,
|
||||
darkTheme: true,
|
||||
backgroundColor: "#FFF",
|
||||
});
|
||||
|
||||
win.loadURL(url);
|
||||
|
||||
win.on("closed", () => {
|
||||
loginWindow = null;
|
||||
});
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
const menu = new Menu();
|
||||
|
||||
const settingsMenu = {
|
||||
playMenu: function () {
|
||||
const settings = {
|
||||
paly: {
|
||||
label: "播放",
|
||||
click: function () {
|
||||
senders.send("play-start");
|
||||
},
|
||||
},
|
||||
addPlayList: {
|
||||
label: "添加到播放列表",
|
||||
click: function () {
|
||||
senders.send("add-play-list");
|
||||
},
|
||||
},
|
||||
collect: {
|
||||
label: "收藏",
|
||||
submenu: [
|
||||
{
|
||||
label: "创建新歌单",
|
||||
click: function () {
|
||||
senders.send("i-like-star");
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
share: {
|
||||
label: "分享",
|
||||
},
|
||||
copyLink: {
|
||||
label: "复制链接",
|
||||
},
|
||||
};
|
||||
menu.append(new MenuItem(settings.paly));
|
||||
menu.append(new MenuItem(settings.addPlayList));
|
||||
menu.append(new MenuItem({ type: "separator" }));
|
||||
menu.append(new MenuItem(settings.collect));
|
||||
menu.append(new MenuItem(settings.share));
|
||||
menu.append(new MenuItem(settings.copyLink));
|
||||
},
|
||||
};
|
||||
|
||||
export function command(mainWindow, winURL) {
|
||||
// 显示播放菜单
|
||||
settingsMenu.playMenu();
|
||||
// 接收显示菜单指令
|
||||
ipcMain.on("show-content-menu", (event) => {
|
||||
senders = event.sender;
|
||||
const win = BrowserWindow.fromWebContents(senders);
|
||||
menu.popup(win);
|
||||
});
|
||||
// 设置app名称
|
||||
app.setName("网易云音乐App");
|
||||
// 关闭window窗口
|
||||
ipcMain.on("window-close", (event) => {
|
||||
app.quit();
|
||||
});
|
||||
// 最大化window窗口
|
||||
ipcMain.on("window-max", (event) => {
|
||||
if (mainWindow.isMaximized()) {
|
||||
mainWindow.unmaximize();
|
||||
} else {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
});
|
||||
// 最小化window窗口
|
||||
ipcMain.on("window-min", (event) => {
|
||||
if (!mainWindow.isMinimized()) {
|
||||
mainWindow.minimize();
|
||||
}
|
||||
});
|
||||
// 新建登录窗口
|
||||
ipcMain.on("open-login-window", (event, url) => {
|
||||
if (loginWindow) {
|
||||
loginWindow.focus();
|
||||
} else {
|
||||
loginWindow = openWindow(url);
|
||||
}
|
||||
});
|
||||
// 关闭登录窗口
|
||||
ipcMain.on("close-login-window", (event) => {
|
||||
loginWindow.close();
|
||||
});
|
||||
// 触发调试 Shift+i
|
||||
globalShortcut.register("Shift+i", () => {
|
||||
require("electron-debug")({ showDevTools: true });
|
||||
});
|
||||
}
|
||||
161
src/electron/menu.js
Normal file
161
src/electron/menu.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
const { Menu, app } = require("electron");
|
||||
|
||||
const version = app.getVersion();
|
||||
|
||||
let win;
|
||||
let updateSource = "menu"; // 更新事件触发来源 menu:通过菜单触发 vue:通过vue页面触发
|
||||
let template = [
|
||||
{
|
||||
label: "编辑",
|
||||
submenu: [
|
||||
{
|
||||
label: "剪切",
|
||||
accelerator: (() => {
|
||||
if (process.platform === "darwin") {
|
||||
return "CmdOrCtrl+X";
|
||||
} else {
|
||||
return "Ctrl+X";
|
||||
}
|
||||
})(),
|
||||
role: "cut",
|
||||
},
|
||||
{
|
||||
label: "复制",
|
||||
accelerator: (() => {
|
||||
if (process.platform === "darwin") {
|
||||
return "CmdOrCtrl+C";
|
||||
} else {
|
||||
return "Ctrl+C";
|
||||
}
|
||||
})(),
|
||||
role: "copy",
|
||||
},
|
||||
{
|
||||
label: "粘贴",
|
||||
accelerator: (() => {
|
||||
if (process.platform === "darwin") {
|
||||
return "CmdOrCtrl+V";
|
||||
} else {
|
||||
return "Ctrl+V";
|
||||
}
|
||||
})(),
|
||||
role: "paste",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "工具",
|
||||
submenu: [
|
||||
{
|
||||
label: "刷新",
|
||||
accelerator: (() => {
|
||||
if (process.platform === "darwin") {
|
||||
return "CmdOrCtrl+R";
|
||||
} else {
|
||||
return "F5";
|
||||
}
|
||||
})(),
|
||||
click: (item, focusedWindow) => {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "全屏",
|
||||
accelerator: (() => {
|
||||
if (process.platform === "darwin") {
|
||||
return "Ctrl+Command+F";
|
||||
} else {
|
||||
return "F11";
|
||||
}
|
||||
})(),
|
||||
click: (item, focusedWindow) => {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "检查",
|
||||
accelerator: "F12",
|
||||
click: (item, focusedWindow) => {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function findReopenMenuItem() {
|
||||
const menu = Menu.getApplicationMenu();
|
||||
if (!menu) return;
|
||||
|
||||
let reopenMenuItem;
|
||||
menu.items.forEach((item) => {
|
||||
if (item.submenu) {
|
||||
item.submenu.items.forEach((item) => {
|
||||
if (item.key === "reopenMenuItem") {
|
||||
reopenMenuItem = item;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return reopenMenuItem;
|
||||
}
|
||||
|
||||
// mac 添加退出
|
||||
if (process.platform === "darwin") {
|
||||
const name = app.getName();
|
||||
template.unshift({
|
||||
label: name + " v" + version,
|
||||
submenu: [
|
||||
{
|
||||
label: "退出",
|
||||
accelerator: "Command+Q",
|
||||
click: () => {
|
||||
app.quit();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
// win 添加更新菜单
|
||||
if (process.platform === "win32") {
|
||||
template.push({
|
||||
label: "帮助",
|
||||
submenu: [
|
||||
{
|
||||
label: `当前版本 v${version}`,
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
label: "检查更新",
|
||||
accelerator: "Ctrl+U",
|
||||
click: (item, focusedWindow) => {
|
||||
// 执行自动更新检查
|
||||
win = focusedWindow;
|
||||
updateSource = "menu";
|
||||
autoUpdater.checkForUpdates();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
const menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
})
|
||||
|
||||
app.on('browser-window-created', () => {
|
||||
let reopenMenuItem = findReopenMenuItem()
|
||||
if (reopenMenuItem) reopenMenuItem.enabled = false
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
let reopenMenuItem = findReopenMenuItem()
|
||||
if (reopenMenuItem) reopenMenuItem.enabled = true
|
||||
})
|
||||
0
src/electron/preload.js
Normal file
0
src/electron/preload.js
Normal file
61
src/electron/services.js
Normal file
61
src/electron/services.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
const express = require("express");
|
||||
const path = require("path");
|
||||
const bodyParser = require('body-parser')
|
||||
const cache = require('../../napi/util/apicache').middleware
|
||||
const fileUpload = require('express-fileupload')
|
||||
|
||||
import routes from "../../napi/routes";
|
||||
|
||||
// Integrate API
|
||||
const app = express()
|
||||
|
||||
// CORS & Preflight request
|
||||
app.use((req, res, next) => {
|
||||
if (req.path !== '/' && !req.path.includes('.')) {
|
||||
res.set({
|
||||
'Access-Control-Allow-Credentials': true,
|
||||
'Access-Control-Allow-Origin': req.headers.origin || '*',
|
||||
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
|
||||
'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
})
|
||||
}
|
||||
req.method === 'OPTIONS' ? res.status(204).end() : next()
|
||||
})
|
||||
|
||||
// cookie parser
|
||||
app.use((req, res, next) => {
|
||||
req.cookies = {}
|
||||
;(req.headers.cookie || '').split(/\s*;\s*/).forEach((pair) => {
|
||||
let crack = pair.indexOf('=')
|
||||
if (crack < 1 || crack == pair.length - 1) return
|
||||
req.cookies[
|
||||
decodeURIComponent(pair.slice(0, crack)).trim()
|
||||
] = decodeURIComponent(pair.slice(crack + 1)).trim()
|
||||
})
|
||||
next()
|
||||
})
|
||||
|
||||
// body parser
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({ extended: false }))
|
||||
|
||||
app.use(fileUpload())
|
||||
|
||||
// static
|
||||
// app.use(express.static(path.join(__dirname, 'public')))
|
||||
|
||||
// cache
|
||||
app.use(cache('2 minutes', (req, res) => res.statusCode === 200))
|
||||
// router
|
||||
|
||||
Object.keys(routes).forEach(route => {
|
||||
app.use(route, routes[route])
|
||||
})
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
const host = process.env.HOST || ''
|
||||
|
||||
app.server = app.listen(port, host, () => {
|
||||
console.log(`server running @ http://${host ? host : 'localhost'}:${port}`)
|
||||
})
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { register } from "register-service-worker";
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
if (process.env.NODE_ENV === "production" && process.env.IS_ELECTRON === 'undefined') {
|
||||
register(`${process.env.BASE_URL}service-worker.js`, {
|
||||
ready() {
|
||||
console.log(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue