mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
✨ feat: 网页端支持 PWA #97
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
splitVendorChunkPlugin,
|
||||
} from "electron-vite";
|
||||
import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
|
||||
import { VitePWA } from "vite-plugin-pwa";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import AutoImport from "unplugin-auto-import/vite";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
@@ -71,6 +72,52 @@ export default defineConfig(({ mode }) => {
|
||||
viteCompression(),
|
||||
// splitVendorChunkPlugin
|
||||
splitVendorChunkPlugin(),
|
||||
// PWA
|
||||
VitePWA({
|
||||
registerType: "autoUpdate",
|
||||
workbox: {
|
||||
clientsClaim: true,
|
||||
skipWaiting: true,
|
||||
cleanupOutdatedCaches: true,
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: /(.*?)\.(woff2|woff|ttf)/,
|
||||
handler: "CacheFirst",
|
||||
options: {
|
||||
cacheName: "file-cache",
|
||||
},
|
||||
},
|
||||
{
|
||||
urlPattern: /(.*?)\.(webp|png|jpe?g|svg|gif|bmp|psd|tiff|tga|eps)/,
|
||||
handler: "CacheFirst",
|
||||
options: {
|
||||
cacheName: "image-cache",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
manifest: {
|
||||
name: loadEnv(mode, process.cwd()).RENDERER_VITE_SITE_TITLE,
|
||||
short_name: loadEnv(mode, process.cwd()).RENDERER_VITE_SITE_TITLE,
|
||||
description: loadEnv(mode, process.cwd()).RENDERER_VITE_SITE_DES,
|
||||
display: "standalone",
|
||||
start_url: "/",
|
||||
theme_color: "#fff",
|
||||
background_color: "#efefef",
|
||||
icons: [
|
||||
{
|
||||
src: "/images/logo/favicon.png",
|
||||
sizes: "200x200",
|
||||
type: "image/png",
|
||||
},
|
||||
{
|
||||
src: "/images/logo/favicon_512.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
// 服务器配置
|
||||
server: {
|
||||
@@ -103,6 +150,9 @@ export default defineConfig(({ mode }) => {
|
||||
win: {
|
||||
icon: resolve(__dirname, "/public/images/logo/favicon.png"),
|
||||
},
|
||||
linux: {
|
||||
icon: resolve(__dirname, "/public/images/logo/favicon.png"),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -41,10 +41,12 @@ class MainProcess {
|
||||
height: { type: "number", default: 740 },
|
||||
},
|
||||
});
|
||||
// 设置应用程序名称
|
||||
if (process.platform === "win32") app.setAppUserModelId(app.getName());
|
||||
// 初始化
|
||||
this.checkApp().then((lockObtained) => {
|
||||
this.checkApp().then(async (lockObtained) => {
|
||||
if (lockObtained) {
|
||||
this.init();
|
||||
await this.init();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -86,9 +88,10 @@ class MainProcess {
|
||||
}
|
||||
|
||||
// 非开发环境启动代理
|
||||
if (!is.dev) {
|
||||
this.mainServer = await startMainServer();
|
||||
}
|
||||
// if (!is.dev) {
|
||||
// this.mainServer = await startMainServer();
|
||||
// }
|
||||
this.mainServer = await startMainServer();
|
||||
|
||||
// 注册应用协议
|
||||
app.setAsDefaultProtocolClient("splayer");
|
||||
@@ -131,6 +134,8 @@ class MainProcess {
|
||||
this.mainWindow.show();
|
||||
// mainWindow.maximize();
|
||||
this.store.set("windowSize", this.mainWindow.getBounds());
|
||||
// 创建系统信息
|
||||
createSystemInfo(this.mainWindow);
|
||||
});
|
||||
|
||||
// 主窗口事件
|
||||
@@ -148,9 +153,10 @@ class MainProcess {
|
||||
this.mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL);
|
||||
}
|
||||
// 生产模式
|
||||
else {
|
||||
this.mainWindow.loadURL(`http://127.0.0.1:${import.meta.env.MAIN_VITE_MAIN_PORT ?? 7899}`);
|
||||
}
|
||||
// else {
|
||||
// this.mainWindow.loadURL(`http://127.0.0.1:${import.meta.env.MAIN_VITE_MAIN_PORT ?? 7899}`);
|
||||
// }
|
||||
this.mainWindow.loadURL(`http://127.0.0.1:${import.meta.env.MAIN_VITE_MAIN_PORT ?? 7899}`);
|
||||
|
||||
// 监听关闭
|
||||
this.mainWindow.on("close", (event) => {
|
||||
@@ -164,13 +170,11 @@ class MainProcess {
|
||||
|
||||
// 主应用程序事件
|
||||
mainAppEvents() {
|
||||
app.on("ready", async () => {
|
||||
app.whenReady().then(async () => {
|
||||
// 创建主窗口
|
||||
this.createWindow();
|
||||
// 检测更新
|
||||
configureAutoUpdater();
|
||||
// 创建系统信息
|
||||
createSystemInfo(this.mainWindow);
|
||||
// 引入主 Ipc
|
||||
mainIpcMain(this.mainWindow);
|
||||
// 注册快捷键
|
||||
|
||||
@@ -19,6 +19,8 @@ const createSystemInfo = (win) => {
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate(createTrayMenu(win)));
|
||||
// 给托盘图标设置气球提示
|
||||
mainTray.setToolTip(app.getName());
|
||||
// 自定义任务栏缩略图
|
||||
createThumbar(win);
|
||||
// 歌曲数据改变时
|
||||
ipcMain.on("songNameChange", (_, val) => {
|
||||
playSongName = val;
|
||||
@@ -29,6 +31,11 @@ const createSystemInfo = (win) => {
|
||||
});
|
||||
ipcMain.on("songStateChange", (_, val) => {
|
||||
playSongState = val;
|
||||
createThumbar(win);
|
||||
});
|
||||
// 监听系统主题改变
|
||||
nativeTheme.on("updated", () => {
|
||||
createThumbar(win);
|
||||
});
|
||||
// 左键事件
|
||||
mainTray.on("click", () => {
|
||||
@@ -45,20 +52,22 @@ const createSystemInfo = (win) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 生成右键菜单
|
||||
const createTrayMenu = (win) => {
|
||||
// 生成图标
|
||||
const createIcon = (name) => {
|
||||
// 系统是否为暗色
|
||||
const isDarkMode = nativeTheme.shouldUseDarkColors;
|
||||
// 生成图标
|
||||
const createIcon = (name) => {
|
||||
return nativeImage
|
||||
.createFromPath(
|
||||
isDarkMode
|
||||
? join(__dirname, `../../public/images/icon/${name}-dark.png`)
|
||||
: join(__dirname, `../../public/images/icon/${name}-light.png`),
|
||||
)
|
||||
.resize({ width: 16, height: 16 });
|
||||
};
|
||||
// 返回图标
|
||||
return nativeImage
|
||||
.createFromPath(
|
||||
isDarkMode
|
||||
? join(__dirname, `../../public/images/icon/${name}-dark.png`)
|
||||
: join(__dirname, `../../public/images/icon/${name}-light.png`),
|
||||
)
|
||||
.resize({ width: 16, height: 16 });
|
||||
};
|
||||
|
||||
// 生成右键菜单
|
||||
const createTrayMenu = (win) => {
|
||||
// 返回菜单
|
||||
return [
|
||||
{
|
||||
@@ -122,4 +131,32 @@ const createTrayMenu = (win) => {
|
||||
];
|
||||
};
|
||||
|
||||
// 自定义任务栏缩略图 - Win
|
||||
const createThumbar = (win) => {
|
||||
win.setThumbarButtons([]);
|
||||
win.setThumbarButtons([
|
||||
{
|
||||
tooltip: "上一曲",
|
||||
icon: createIcon("prev"),
|
||||
click: () => {
|
||||
win.webContents.send("playNextOrPrev", "prev");
|
||||
},
|
||||
},
|
||||
{
|
||||
tooltip: playSongState ? "暂停" : "播放",
|
||||
icon: createIcon(playSongState ? "pause" : "play"),
|
||||
click() {
|
||||
win.webContents.send("playOrPause");
|
||||
},
|
||||
},
|
||||
{
|
||||
tooltip: "下一曲",
|
||||
icon: createIcon("next"),
|
||||
click: () => {
|
||||
win.webContents.send("playNextOrPrev", "next");
|
||||
},
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
export default createSystemInfo;
|
||||
|
||||
11
package.json
11
package.json
@@ -6,9 +6,11 @@
|
||||
"author": "imsyy",
|
||||
"home": "https://imsyy.top",
|
||||
"github": "https://github.com/imsyy/SPlayer",
|
||||
"repository": "github:imsyy/SPlayer",
|
||||
"engines": {
|
||||
"node": ">=16.16.0"
|
||||
},
|
||||
"packageManager": "pnpm@8.12.0",
|
||||
"scripts": {
|
||||
"format": "prettier --write .",
|
||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
|
||||
@@ -51,13 +53,13 @@
|
||||
"@vitejs/plugin-vue": "^4.3.1",
|
||||
"@vue/eslint-config-prettier": "^8.0.0",
|
||||
"ajv": "^8.12.0",
|
||||
"electron": "^25.6.0",
|
||||
"electron-builder": "^24.6.4",
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.9.1",
|
||||
"electron-log": "^5.0.1",
|
||||
"electron-vite": "^1.0.27",
|
||||
"electron-vite": "^1.0.29",
|
||||
"eslint": "^8.47.0",
|
||||
"eslint-plugin-vue": "^9.17.0",
|
||||
"naive-ui": "^2.34.4",
|
||||
"naive-ui": "^2.35.0",
|
||||
"prettier": "^3.0.2",
|
||||
"sass": "^1.66.1",
|
||||
"terser": "^5.19.2",
|
||||
@@ -65,6 +67,7 @@
|
||||
"unplugin-vue-components": "^0.25.1",
|
||||
"vite": "^4.4.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-pwa": "^0.17.4",
|
||||
"vue": "^3.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
2283
pnpm-lock.yaml
generated
2283
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -105,6 +105,7 @@ const openDropdown = (e, data, song, index, sourceId) => {
|
||||
(playlist) => playlist.userId === userId,
|
||||
);
|
||||
// 当前状态
|
||||
const isFm = playMode.value === "fm";
|
||||
const isLocalSong = song?.path ? true : false;
|
||||
const isCloud = router.currentRoute.value.name === "cloud";
|
||||
const isUserPlaylist = sourceId !== 0 && userPlaylistsData.some((pl) => pl.id == sourceId);
|
||||
@@ -136,7 +137,7 @@ const openDropdown = (e, data, song, index, sourceId) => {
|
||||
{
|
||||
key: "next-play",
|
||||
label: "下一首播放",
|
||||
show: playSongData.value?.id === song.id || playMode.value === "fm" ? false : true,
|
||||
show: playSongData.value?.id !== song.id && !isFm,
|
||||
props: {
|
||||
onClick: () => {
|
||||
addSongToNext(song);
|
||||
|
||||
Reference in New Issue
Block a user