chore: 整理electron目录

This commit is contained in:
qier222 2022-05-13 19:30:13 +08:00
parent ca4725a46e
commit 8d7ae405a6
No known key found for this signature in database
GPG key ID: 9C85007ED905F14D
15 changed files with 160 additions and 68 deletions

View file

@ -5,7 +5,7 @@ import { Request, Response } from 'express'
import log from './log' import log from './log'
import fs from 'fs' import fs from 'fs'
import * as musicMetadata from 'music-metadata' import * as musicMetadata from 'music-metadata'
import { APIs, APIsParams, APIsResponse } from '../shared/CacheAPIs' import { APIs, APIsParams, APIsResponse } from '@/shared/CacheAPIs'
import { TablesStructures } from './db' import { TablesStructures } from './db'
class Cache { class Cache {

View file

@ -3,10 +3,9 @@ import { app } from 'electron'
import fs from 'fs' import fs from 'fs'
import SQLite3 from 'better-sqlite3' import SQLite3 from 'better-sqlite3'
import log from './log' import log from './log'
import { createFileIfNotExist } from './utils' import { createFileIfNotExist, dirname } from './utils'
import pkg from '../../package.json' import pkg from '../../../package.json'
import { compare, validate } from 'compare-versions' import { compare, validate } from 'compare-versions'
import { dirname } from './utils'
export const enum Tables { export const enum Tables {
Track = 'Track', Track = 'Track',

View file

@ -15,6 +15,7 @@ import { initIpcMain } from './ipcMain'
import { createTray, YPMTray } from './tray' import { createTray, YPMTray } from './tray'
import { IpcChannels } from '@/shared/IpcChannels' import { IpcChannels } from '@/shared/IpcChannels'
import { createTaskbar, Thumbar } from './windowsTaskbar' import { createTaskbar, Thumbar } from './windowsTaskbar'
import { createMenu } from './menu'
import { Store as State, initialState } from '@/shared/store' import { Store as State, initialState } from '@/shared/store'
import { isDev, isWindows, isLinux, isMac } from './utils' import { isDev, isWindows, isLinux, isMac } from './utils'
@ -63,6 +64,7 @@ class Main {
this.handleAppEvents() this.handleAppEvents()
this.handleWindowEvents() this.handleWindowEvents()
this.createTray() this.createTray()
createMenu(this.win!)
this.createThumbar() this.createThumbar()
initIpcMain(this.win, this.tray, this.thumbar, this.store) initIpcMain(this.win, this.tray, this.thumbar, this.store)
this.initDevTools() this.initDevTools()
@ -76,13 +78,9 @@ class Main {
const { const {
default: installExtension, default: installExtension,
REACT_DEVELOPER_TOOLS, REACT_DEVELOPER_TOOLS,
REDUX_DEVTOOLS,
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
} = require('electron-devtools-installer') } = require('electron-devtools-installer')
installExtension(REACT_DEVELOPER_TOOLS.id).catch((err: any) => installExtension(REACT_DEVELOPER_TOOLS.id).catch((err: unknown) =>
log.info('An error occurred: ', err)
)
installExtension(REDUX_DEVTOOLS.id).catch((err: any) =>
log.info('An error occurred: ', err) log.info('An error occurred: ', err)
) )
@ -134,25 +132,26 @@ class Main {
disableCORS() { disableCORS() {
if (!this.win) return if (!this.win) return
function UpsertKeyValue(obj, keyToChange, value) { const upsertKeyValue = (
const keyToChangeLower = keyToChange.toLowerCase() object: Record<string, string | string[]>,
for (const key of Object.keys(obj)) { keyToChange: string,
if (key.toLowerCase() === keyToChangeLower) { value: string[]
// Reassign old key ) => {
obj[key] = value if (!object) return
// Done for (const key of Object.keys(object)) {
return if (key.toLowerCase() === keyToChange.toLowerCase()) {
object[key] = value
} }
} }
// Insert at end instead object[keyToChange] = value
obj[keyToChange] = value
} }
this.win.webContents.session.webRequest.onBeforeSendHeaders( this.win.webContents.session.webRequest.onBeforeSendHeaders(
(details, callback) => { (details, callback) => {
const { requestHeaders, url } = details const { requestHeaders, url } = details
UpsertKeyValue(requestHeaders, 'Access-Control-Allow-Origin', ['*']) upsertKeyValue(requestHeaders, 'access-control-allow-origin', ['*'])
// 不加这几个 header 的话,使用 axios 加载 YouTube 音频会很慢
if (url.includes('googlevideo.com')) { if (url.includes('googlevideo.com')) {
requestHeaders['Sec-Fetch-Mode'] = 'no-cors' requestHeaders['Sec-Fetch-Mode'] = 'no-cors'
requestHeaders['Sec-Fetch-Dest'] = 'audio' requestHeaders['Sec-Fetch-Dest'] = 'audio'
@ -166,8 +165,10 @@ class Main {
this.win.webContents.session.webRequest.onHeadersReceived( this.win.webContents.session.webRequest.onHeadersReceived(
(details, callback) => { (details, callback) => {
const { responseHeaders } = details const { responseHeaders } = details
UpsertKeyValue(responseHeaders, 'Access-Control-Allow-Origin', ['*']) if (responseHeaders) {
UpsertKeyValue(responseHeaders, 'Access-Control-Allow-Headers', ['*']) upsertKeyValue(responseHeaders, 'access-control-allow-origin', ['*'])
upsertKeyValue(responseHeaders, 'access-control-allow-headers', ['*'])
}
callback({ callback({
responseHeaders, responseHeaders,
}) })

View file

@ -1,12 +1,12 @@
import { BrowserWindow, ipcMain, app } from 'electron' import { BrowserWindow, ipcMain, app } from 'electron'
import { db, Tables } from './db' import { db, Tables } from './db'
import { IpcChannels, IpcChannelsParams } from '../shared/IpcChannels' import { IpcChannels, IpcChannelsParams } from '@/shared/IpcChannels'
import cache from './cache' import cache from './cache'
import log from './log' import log from './log'
import fs from 'fs' import fs from 'fs'
import Store from 'electron-store' import Store from 'electron-store'
import { TypedElectronStore } from './index' import { TypedElectronStore } from './index'
import { APIs } from '../shared/CacheAPIs' import { APIs } from '@/shared/CacheAPIs'
import { YPMTray } from './tray' import { YPMTray } from './tray'
import { Thumbar } from './windowsTaskbar' import { Thumbar } from './windowsTaskbar'
import fastFolderSize from 'fast-folder-size' import fastFolderSize from 'fast-folder-size'

View file

@ -0,0 +1,74 @@
import {
BrowserWindow,
Menu,
MenuItem,
MenuItemConstructorOptions,
shell,
} from 'electron'
import { logsPath, isMac } from './utils'
import { exec } from 'child_process'
export const createMenu = (win: BrowserWindow) => {
const template: Array<MenuItemConstructorOptions | MenuItem> = [
{ role: 'appMenu' },
{ role: 'editMenu' },
{ role: 'viewMenu' },
{ role: 'windowMenu' },
{
label: '帮助',
submenu: [
{
label: '打开日志文件目录',
click: async () => {
if (isMac) {
exec(`open ${logsPath}`)
} else {
// TODO: 测试Windows和Linux是否能正确打开日志目录
shell.openPath(logsPath)
}
},
},
{
label: '打开开发者工具',
click: async () => {
win.webContents.openDevTools()
},
},
{
label: '反馈问题',
click: async () => {
await shell.openExternal(
'https://github.com/qier222/YesPlayMusic/issues/new'
)
},
},
{ type: 'separator' },
{
label: '访问 GitHub 仓库',
click: async () => {
await shell.openExternal('https://github.com/qier222/YesPlayMusic')
},
},
{
label: '访问论坛',
click: async () => {
await shell.openExternal(
'https://github.com/qier222/YesPlayMusic/discussions'
)
},
},
{
label: '加入交流群',
click: async () => {
await shell.openExternal(
'https://github.com/qier222/YesPlayMusic/discussions'
)
},
},
],
},
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}

View file

@ -0,0 +1,19 @@
import log from './log'
import { app } from 'electron'
import {
createDirIfNotExist,
devUserDataPath,
isDev,
portableUserDataPath,
} from './utils'
if (isDev) {
createDirIfNotExist(devUserDataPath)
app.setPath('appData', devUserDataPath)
}
if (process.env.PORTABLE_EXECUTABLE_DIR) {
createDirIfNotExist(portableUserDataPath)
app.setPath('appData', portableUserDataPath)
}
log.info(`[index] userData path: ${app.getPath('userData')}`)

View file

@ -1,6 +1,6 @@
import * as Sentry from '@sentry/node' import * as Sentry from '@sentry/node'
import * as Tracing from '@sentry/tracing' import * as Tracing from '@sentry/tracing'
import pkg from '../../package.json' import pkg from '../../../package.json'
import log from './log' import log from './log'
log.info(`[sentry] sentry initializing`) log.info(`[sentry] sentry initializing`)

View file

@ -6,12 +6,12 @@ import cache from './cache'
import fileUpload from 'express-fileupload' import fileUpload from 'express-fileupload'
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
import { db, Tables } from 'db' import { db, Tables } from './db'
import { app } from 'electron' import { app } from 'electron'
import type { FetchAudioSourceResponse } from '@/shared/api/Track' import type { FetchAudioSourceResponse } from '@/shared/api/Track'
import UNM from '@unblockneteasemusic/rust-napi' import UNM from '@unblockneteasemusic/rust-napi'
import { APIs as CacheAPIs } from '../shared/CacheAPIs' import { APIs as CacheAPIs } from '@/shared/CacheAPIs'
import { isProd } from 'utils' import { isProd } from './utils'
class Server { class Server {
port = Number( port = Number(
@ -241,21 +241,21 @@ class Server {
}) })
} }
// try { try {
// const fromCache = await getFromCache(id) const fromCache = await getFromCache(id)
// if (fromCache) { if (fromCache) {
// res.status(200).send(fromCache) res.status(200).send(fromCache)
// return return
// } }
// } catch (error) { } catch (error) {
// log.error(`[server] getFromCache failed: ${String(error)}`) log.error(`[server] getFromCache failed: ${String(error)}`)
// } }
// const fromNetease = await getFromNetease(req) const fromNetease = await getFromNetease(req)
// if (fromNetease?.code === 200 && !fromNetease?.data?.[0].freeTrialInfo) { if (fromNetease?.code === 200 && !fromNetease?.data?.[0].freeTrialInfo) {
// res.status(200).send(fromNetease) res.status(200).send(fromNetease)
// return return
// } }
try { try {
const fromUNM = await getFromUNM(id, req) const fromUNM = await getFromUNM(id, req)
@ -267,11 +267,11 @@ class Server {
log.error(`[server] getFromNetease failed: ${String(error)}`) log.error(`[server] getFromNetease failed: ${String(error)}`)
} }
// if (fromNetease?.data?.[0].freeTrialInfo) { if (fromNetease?.data?.[0].freeTrialInfo) {
// fromNetease.data[0].url = '' fromNetease.data[0].url = ''
// } }
// res.status(fromNetease?.code ?? 500).send(fromNetease) res.status(fromNetease?.code ?? 500).send(fromNetease)
} }
this.app.get('/netease/song/url', handler) this.app.get('/netease/song/url', handler)

View file

@ -34,7 +34,7 @@ function createNativeImage(filename: string) {
} }
function createMenuTemplate(win: BrowserWindow): MenuItemConstructorOptions[] { function createMenuTemplate(win: BrowserWindow): MenuItemConstructorOptions[] {
let template: MenuItemConstructorOptions[] = const template: MenuItemConstructorOptions[] =
process.platform === 'linux' process.platform === 'linux'
? [ ? [
{ {

View file

@ -1,5 +1,23 @@
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
import pkg from '../../../package.json'
export const isDev = process.env.NODE_ENV === 'development'
export const isProd = process.env.NODE_ENV === 'production'
export const isWindows = process.platform === 'win32'
export const isMac = process.platform === 'darwin'
export const isLinux = process.platform === 'linux'
export const dirname = isDev ? process.cwd() : __dirname
export const devUserDataPath = path.resolve(process.cwd(), '../../tmp/userData')
export const portableUserDataPath = path.resolve(
process.env.PORTABLE_EXECUTABLE_DIR || '',
'./YesPlayMusic-UserData'
)
export const logsPath = {
linux: `~/.config/${pkg.productName}/logs`,
darwin: `~/Library/Logs/${pkg.productName}/`,
win32: `%USERPROFILE%\\AppData\\Roaming\\${pkg.productName}\\logs`,
}[process.platform as 'darwin' | 'win32' | 'linux']
export const createDirIfNotExist = (dir: string) => { export const createDirIfNotExist = (dir: string) => {
if (!fs.existsSync(dir)) { if (!fs.existsSync(dir)) {
@ -13,10 +31,3 @@ export const createFileIfNotExist = (file: string) => {
fs.writeFileSync(file, '') fs.writeFileSync(file, '')
} }
} }
export const isDev = process.env.NODE_ENV === 'development'
export const isProd = process.env.NODE_ENV === 'production'
export const isWindows = process.platform === 'win32'
export const isMac = process.platform === 'darwin'
export const isLinux = process.platform === 'linux'
export const dirname = isDev ? process.cwd() : __dirname

View file

@ -1,11 +0,0 @@
import log from './log'
import path from 'path'
import { app } from 'electron'
import { createDirIfNotExist, isDev } from './utils'
if (isDev) {
const devUserDataPath = path.resolve(process.cwd(), '../../tmp/userData')
createDirIfNotExist(devUserDataPath)
app.setPath('appData', devUserDataPath)
}
log.info(`[index] userData path: ${app.getPath('userData')}`)

View file

@ -23,13 +23,13 @@ const TAG = '[script/build.main.ts]'
const spinner = ora(`${TAG} Main Process Building...`) const spinner = ora(`${TAG} Main Process Building...`)
const options = { const options = {
entryPoints: ['./index.ts', './rendererPreload.ts'], entryPoints: ['./main/index.ts', './main/rendererPreload.ts'],
outdir: './dist', outdir: './dist',
platform: 'node', platform: 'node',
format: 'cjs', format: 'cjs',
bundle: true, bundle: true,
sourcemap: true,
define: envForEsbuild, define: envForEsbuild,
minify: true,
external: [ external: [
...builtinModules.filter( ...builtinModules.filter(
x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x) x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x)
@ -95,7 +95,6 @@ if (argv.watch) {
...options.define, ...options.define,
'process.env.NODE_ENV': '"production"', 'process.env.NODE_ENV': '"production"',
}, },
minify: true,
}) })
.then(() => { .then(() => {
console.log(TAG, pc.green('Main Process Build Succeeded.')) console.log(TAG, pc.green('Main Process Build Succeeded.'))