├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── public ├── favicon.ico ├── index.html ├── orange.ico ├── orange512.png └── preload.js ├── show.gif ├── src ├── App.vue ├── assets │ ├── defaultcur.png │ └── pointer.png ├── background.js ├── common │ └── reset.less ├── main.js ├── router │ └── index.js ├── store │ └── index.js └── views │ └── Home.vue ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: ["plugin:vue/essential", "@vue/prettier"], 7 | rules: { 8 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off", 9 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off" 10 | }, 11 | parserOptions: { 12 | parser: "babel-eslint" 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | #Electron-builder output 24 | /dist_electron -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Local music player 2 | 3 | ![img](show.gif) 4 | 5 | ## Usage 6 | 7 | Chose orangePlayer to play your music, support **.mp3 .wav .flac .ogg .m4a** .file. 8 | 9 | Get more info to check Here: [https://segmentfault.com/a/1190000037613988](https://segmentfault.com/a/1190000037613988) 10 | 11 | ## Introduce 12 | 13 | 1. Support mac and windows; 14 | 15 | 2. Update the electron version to v11; 16 | 17 | 3. Autoupdate 18 | 19 | ## Project setup 20 | 21 | ``` 22 | yarn install 23 | ``` 24 | 25 | ### Compiles and hot-reloads for development 26 | 27 | ``` 28 | yarn electron:serve 29 | ``` 30 | 31 | ### Compiles and minifies for production 32 | 33 | ``` 34 | yarn electron:build 35 | ``` 36 | 37 | ### Customize configuration 38 | 39 | See [Configuration Reference](https://cli.vuejs.org/config/). 40 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orange-player", 3 | "version": "0.2.8", 4 | "author": "kerinlin", 5 | "description": "Local wave music player", 6 | "private": true, 7 | "scripts": { 8 | "serve": "vue-cli-service serve", 9 | "build": "vue-cli-service build", 10 | "lint": "vue-cli-service lint", 11 | "electron:build": "vue-cli-service electron:build", 12 | "electron:serve": "vue-cli-service electron:serve", 13 | "electron:publish": "vue-cli-service electron:build -p always", 14 | "postinstall": "electron-builder install-app-deps", 15 | "postuninstall": "electron-builder install-app-deps" 16 | }, 17 | "main": "background.js", 18 | "dependencies": { 19 | "core-js": "^3.4.3", 20 | "electron-updater": "^4.3.5", 21 | "normalize.css": "^8.0.1", 22 | "stream-to-blob": "^2.0.1", 23 | "vue": "^2.6.10", 24 | "vue-router": "^3.1.3", 25 | "vuex": "^3.1.2", 26 | "wavesurfer.js": "^4.1.1" 27 | }, 28 | "devDependencies": { 29 | "@vue/cli-plugin-babel": "^4.1.0", 30 | "@vue/cli-plugin-eslint": "^4.1.0", 31 | "@vue/cli-service": "^4.1.0", 32 | "@vue/eslint-config-prettier": "^5.0.0", 33 | "babel-eslint": "^10.0.3", 34 | "electron": "^11.0.3", 35 | "eslint": "^5.16.0", 36 | "eslint-plugin-prettier": "^3.1.1", 37 | "eslint-plugin-vue": "^5.0.0", 38 | "less": "^3.0.4", 39 | "less-loader": "^5.0.0", 40 | "lint-staged": "^9.4.3", 41 | "prettier": "^1.19.1", 42 | "vue-cli-plugin-electron-builder": "^2.0.0-rc.5", 43 | "vue-template-compiler": "^2.6.10" 44 | }, 45 | "gitHooks": { 46 | "pre-commit": "lint-staged" 47 | }, 48 | "lint-staged": { 49 | "*.{js,vue}": [ 50 | "vue-cli-service lint", 51 | "git add" 52 | ] 53 | } 54 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 橙子播放器【舟舟专属】 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/orange.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/public/orange.ico -------------------------------------------------------------------------------- /public/orange512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/public/orange512.png -------------------------------------------------------------------------------- /public/preload.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const electron = require("electron"); 4 | window.fs = fs; 5 | window.path = path; 6 | window.electron = electron; 7 | -------------------------------------------------------------------------------- /show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/show.gif -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 25 | 26 | 53 | -------------------------------------------------------------------------------- /src/assets/defaultcur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/src/assets/defaultcur.png -------------------------------------------------------------------------------- /src/assets/pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kerinlin/localMusicPlayer/2b79bda84170da2775d32795a5f3354039a0b500/src/assets/pointer.png -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const electron = require("electron"); 3 | import { app, protocol, BrowserWindow, dialog } from "electron"; 4 | const { ipcMain } = require("electron"); 5 | const path = require("path"); 6 | import { 7 | createProtocol 8 | // installVueDevtools 9 | } from "vue-cli-plugin-electron-builder/lib"; 10 | import { autoUpdater } from "electron-updater"; 11 | const isDevelopment = process.env.NODE_ENV !== "production"; 12 | const globalShortcut = electron.globalShortcut; 13 | // Keep a global reference of the window object, if you don't, the window will 14 | // be closed automatically when the JavaScript object is garbage collected. 15 | let win; 16 | 17 | // Scheme must be registered before the app is ready 18 | protocol.registerSchemesAsPrivileged([ 19 | { scheme: "app", privileges: { secure: true, standard: true } } 20 | ]); 21 | 22 | function createWindow() { 23 | // Create the browser window. 24 | win = new BrowserWindow({ 25 | width: 584, 26 | height: 361, 27 | autoHideMenuBar: true, 28 | frame: false, 29 | resizable: false, 30 | titleBarStyle: "hidden", 31 | webPreferences: { 32 | nodeIntegration: true, 33 | preload: path.join(app.getAppPath(), "preload.js") 34 | } 35 | }); 36 | 37 | if (process.env.WEBPACK_DEV_SERVER_URL) { 38 | // Load the url of the dev server if in development mode 39 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL); 40 | if (!process.env.IS_TEST) win.webContents.openDevTools(); 41 | } else { 42 | createProtocol("app"); 43 | // Load the index.html when not in development 44 | win.loadURL("app://./index.html"); 45 | autoUpdater.checkForUpdates(); 46 | } 47 | 48 | win.on("closed", () => { 49 | win = null; 50 | }); 51 | } 52 | 53 | let filePath; 54 | 55 | // windows通过process.argv获取打开文件的路径 56 | if (process.platform === "win32") { 57 | filePath = process.argv[1]; 58 | } 59 | 60 | // mac监听open-file事件,获取打开文件的路径 61 | app.on("open-file", (event, path) => { 62 | // win.webContents.send("path", path); 63 | filePath = path; 64 | }); 65 | 66 | // 监听渲染进程的获取路径要求,把路径信息返回给渲染进程 67 | ipcMain.on("getPath", () => { 68 | win.webContents.send("path", filePath); 69 | }); 70 | 71 | // Quit when all windows are closed. 72 | app.on("window-all-closed", () => { 73 | // On macOS it is common for applications and their menu bar 74 | // to stay active until the user quits explicitly with Cmd + Q 75 | if (process.platform !== "darwin") { 76 | app.quit(); 77 | } 78 | }); 79 | 80 | app.on("activate", () => { 81 | // On macOS it's common to re-create a window in the app when the 82 | // dock icon is clicked and there are no other windows open. 83 | if (win === null) { 84 | createWindow(); 85 | } 86 | }); 87 | 88 | // This method will be called when Electron has finished 89 | // initialization and is ready to create browser windows. 90 | // Some APIs can only be used after this event occurs. 91 | 92 | const gotTheLock = app.requestSingleInstanceLock(); 93 | if (gotTheLock) { 94 | app.on("second-instance", (event, commandLine, workingDirectory) => { 95 | console.log(event, workingDirectory); 96 | // 监听是否有第二个实例,向渲染进程发送第二个实例的本地路径 97 | win.webContents.send("path", `${commandLine[commandLine.length - 1]}`); 98 | if (win) { 99 | if (win.isMinimized()) win.restore(); 100 | win.focus(); 101 | } 102 | }); 103 | 104 | app.on("ready", async () => { 105 | // 正式环境开控制台方便调试 106 | globalShortcut.register("CommandOrControl+K", function() { 107 | win.webContents.openDevTools(); 108 | }); 109 | createWindow(); 110 | }); 111 | } else { 112 | app.quit(); 113 | } 114 | 115 | ipcMain.on("close", () => { 116 | win.close(); 117 | app.quit(); 118 | }); 119 | ipcMain.on("minimize", () => { 120 | win.minimize(); 121 | }); 122 | autoUpdater.on("checking-for-update", () => {}); 123 | autoUpdater.on("update-available", () => { 124 | dialog.showMessageBox({ 125 | title: "新版本发布", 126 | message: "有新内容更新,稍后将重新为您安装", 127 | buttons: ["确定"], 128 | type: "info", 129 | noLink: true 130 | }); 131 | }); 132 | // autoUpdater.on("update-not-available", (info) => {}); 133 | // autoUpdater.on("error", (err) => {}); 134 | // autoUpdater.on("download-progress", (progressObj) => {}); 135 | autoUpdater.on("update-downloaded", () => { 136 | autoUpdater.quitAndInstall(); 137 | }); 138 | // Exit cleanly on request from parent process in development mode. 139 | if (isDevelopment) { 140 | if (process.platform === "win32") { 141 | process.on("message", data => { 142 | if (data === "graceful-exit") { 143 | app.quit(); 144 | } 145 | }); 146 | } else { 147 | process.on("SIGTERM", () => { 148 | app.quit(); 149 | }); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/common/reset.less: -------------------------------------------------------------------------------- 1 | body { 2 | cursor: url(../assets/defaultcur.png), default; 3 | -webkit-app-region: drag; 4 | } 5 | button { 6 | -webkit-app-region: no-drag; 7 | } 8 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | import router from "./router"; 4 | import store from "./store"; 5 | import "normalize.css"; 6 | import "./common/reset.less"; 7 | Vue.config.productionTip = false; 8 | 9 | new Vue({ 10 | router, 11 | store, 12 | render: h => h(App) 13 | }).$mount("#app"); 14 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | import Home from "../views/Home.vue"; 4 | 5 | Vue.use(VueRouter); 6 | 7 | const routes = [ 8 | { 9 | path: "/", 10 | name: "home", 11 | component: Home 12 | } 13 | ]; 14 | 15 | const router = new VueRouter({ 16 | routes 17 | }); 18 | 19 | export default router; 20 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | 4 | Vue.use(Vuex); 5 | 6 | export default new Vuex.Store({ 7 | state: {}, 8 | mutations: {}, 9 | actions: {}, 10 | modules: {} 11 | }); 12 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 201 | 299 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: false, 3 | pluginOptions: { 4 | electronBuilder: { 5 | builderOptions: { 6 | appId: "com.electron.zzplayer", 7 | productName: "OrangePlayer", 8 | publish: ["github"], 9 | fileAssociations: [ 10 | { 11 | ext: ["mp3", "wav", "flac", "ogg", "m4a"], 12 | name: "music", 13 | role: "Editor" 14 | } 15 | ], 16 | win: { 17 | icon: "public/orange.ico" 18 | }, 19 | mac: { 20 | target: "dmg", 21 | icon: "public/orange512.png" 22 | }, 23 | nsis: { 24 | oneClick: false, // 是否一键安装,建议为 false,可以让用户点击下一步、下一步、下一步的形式安装程序,如果为true,当用户双击构建好的程序,自动安装程序并打开,即:一键安装 25 | allowToChangeInstallationDirectory: true // 允许修改安装目录,建议为 true,是否允许用户改变安装目录,默认是不允许 26 | } 27 | } 28 | } 29 | } 30 | }; 31 | --------------------------------------------------------------------------------