feat: 网页端支持 PWA #97

This commit is contained in:
imsyy
2023-12-12 18:11:28 +08:00
parent 6046e5a153
commit 024ff1773e
6 changed files with 2316 additions and 118 deletions

View File

@@ -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"),
},
},
},
};

View File

@@ -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);
// 注册快捷键

View File

@@ -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;

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);