feat: windows缩略图工具栏 (#1551)

* 从 v1 引入图标

* feat: windows缩略图工具栏

* 更新windows任务栏控制图标

图标基于microsoft fluent icon修改
移除like和unlike

* update

* 启动时显示taskbar buttons
This commit is contained in:
memorydream 2022-04-29 21:16:46 +08:00 committed by GitHub
parent d3e44541fb
commit 07d7564b1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 122 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

View file

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 223 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 191 B

After

Width:  |  Height:  |  Size: 191 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 308 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 311 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 953 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 344 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 932 B

After

Width:  |  Height:  |  Size: 932 B

Before After
Before After

View file

@ -14,6 +14,7 @@ import log from './log'
import { initIpcMain } from './ipcMain'
import { createTray, YPMTray } from './tray'
import { IpcChannels } from '@/shared/IpcChannels'
import { createTaskbar, Thumbar } from './windowsTaskbar'
const isWindows = process.platform === 'win32'
const isMac = process.platform === 'darwin'
@ -32,6 +33,7 @@ interface TypedElectronStore {
class Main {
win: BrowserWindow | null = null
tray: YPMTray | null = null
thumbar: Thumbar | null = null
store = new Store<TypedElectronStore>({
defaults: {
window: {
@ -62,7 +64,8 @@ class Main {
this.handleAppEvents()
this.handleWindowEvents()
this.createTray()
initIpcMain(this.win, this.tray)
this.createThumbar()
initIpcMain(this.win, this.tray, this.thumbar)
this.initDevTools()
})
}
@ -93,6 +96,10 @@ class Main {
}
}
createThumbar() {
if (isWindows) this.thumbar = createTaskbar(this.win!)
}
createWindow() {
const options: BrowserWindowConstructorOptions = {
title: 'YesPlayMusic',
@ -150,7 +157,7 @@ class Main {
handleAppEvents() {
app.on('window-all-closed', () => {
this.win = null
if (process.platform !== 'darwin') app.quit()
if (!isMac) app.quit()
})
app.on('second-instance', () => {

View file

@ -6,6 +6,7 @@ import log from './log'
import fs from 'fs'
import { APIs } from '../shared/CacheAPIs'
import { YPMTray } from './tray'
import { Thumbar } from './windowsTaskbar'
const on = <T extends keyof IpcChannelsParams>(
channel: T,
@ -14,9 +15,14 @@ const on = <T extends keyof IpcChannelsParams>(
ipcMain.on(channel, listener)
}
export function initIpcMain(win: BrowserWindow | null, tray: YPMTray | null) {
export function initIpcMain(
win: BrowserWindow | null,
tray: YPMTray | null,
thumbar: Thumbar | null
) {
initWindowIpcMain(win)
initTrayIpcMain(tray)
initTaskbarIpcMain(thumbar)
}
/**
@ -45,7 +51,7 @@ function initWindowIpcMain(win: BrowserWindow | null) {
function initTrayIpcMain(tray: YPMTray | null) {
on(IpcChannels.SetTrayTooltip, (e, { text }) => tray?.setTooltip(text))
on(IpcChannels.SetTrayLikeState, (e, { isLiked }) =>
on(IpcChannels.Like, (e, { isLiked }) =>
tray?.setLikeState(isLiked)
)
@ -55,6 +61,15 @@ function initTrayIpcMain(tray: YPMTray | null) {
on(IpcChannels.Repeat, (e, { mode }) => tray?.setRepeatMode(mode))
}
/**
* thumbar对象的事件
* @param {Thumbar} thumbar
*/
function initTaskbarIpcMain(thumbar: Thumbar | null) {
on(IpcChannels.Play, () => thumbar?.setPlayState(true))
on(IpcChannels.Pause, () => thumbar?.setPlayState(false))
}
/**
* API缓存
*/

View file

@ -12,8 +12,8 @@ import { RepeatMode } from '@/shared/playerDataTypes'
const iconDirRoot =
process.env.NODE_ENV === 'development'
? path.join(process.cwd(), './src/main/assets/icons')
: path.join(__dirname, './assets/icons')
? path.join(process.cwd(), './src/main/assets/icons/tray')
: path.join(__dirname, './assets/icons/tray')
enum MenuItemIDs {
Play = 'play',

View file

@ -0,0 +1,86 @@
import { IpcChannels } from '@/shared/IpcChannels'
import { BrowserWindow, nativeImage, ThumbarButton } from 'electron'
import path from 'path'
enum ItemKeys {
Play = 'play',
Pause = 'pause',
Previous = 'previous',
Next = 'next',
}
type ThumbarButtonMap = Map<ItemKeys, ThumbarButton>
const iconDirRoot =
process.env.NODE_ENV === 'development'
? path.join(process.cwd(), './src/main/assets/icons/taskbar')
: path.join(__dirname, './assets/icons/taskbar')
function createNativeImage(filename: string) {
return nativeImage.createFromPath(path.join(iconDirRoot, filename))
}
function createThumbarButtons(win: BrowserWindow): ThumbarButtonMap {
return new Map<ItemKeys, ThumbarButton>()
.set(ItemKeys.Play, {
click: () => win.webContents.send(IpcChannels.Play),
icon: createNativeImage('play.png'),
tooltip: '播放',
})
.set(ItemKeys.Pause, {
click: () => win.webContents.send(IpcChannels.Pause),
icon: createNativeImage('pause.png'),
tooltip: '暂停',
})
.set(ItemKeys.Previous, {
click: () => win.webContents.send(IpcChannels.Previous),
icon: createNativeImage('previous.png'),
tooltip: '上一首',
})
.set(ItemKeys.Next, {
click: () => win.webContents.send(IpcChannels.Next),
icon: createNativeImage('next.png'),
tooltip: '下一首',
})
}
export interface Thumbar {
setPlayState(isPlaying: boolean): void
}
class ThumbarImpl implements Thumbar {
private _win: BrowserWindow
private _buttons: ThumbarButtonMap
private _playOrPause: ThumbarButton
private _previous: ThumbarButton
private _next: ThumbarButton
constructor(win: BrowserWindow) {
this._win = win
this._buttons = createThumbarButtons(win)
this._playOrPause = this._buttons.get(ItemKeys.Play)!
this._previous = this._buttons.get(ItemKeys.Previous)!
this._next = this._buttons.get(ItemKeys.Next)!
}
private _updateThumbarButtons(clear: boolean) {
this._win.setThumbarButtons(
clear
? []
: [this._previous, this._playOrPause, this._next]
)
}
setPlayState(isPlaying: boolean) {
this._playOrPause = this._buttons.get(
isPlaying ? ItemKeys.Pause : ItemKeys.Play
)!
this._updateThumbarButtons(false)
}
}
export function createTaskbar(win: BrowserWindow): Thumbar {
return new ThumbarImpl(win)
}

View file

@ -33,7 +33,7 @@ const IpcRendererReact = () => {
}, [track])
useEffect(() => {
window.ipcRenderer?.send(IpcChannels.SetTrayLikeState, {
window.ipcRenderer?.send(IpcChannels.Like, {
isLiked: userLikedSongs?.ids?.includes(track?.id ?? 0) ?? false,
})
}, [userLikedSongs, track])
@ -46,6 +46,13 @@ const IpcRendererReact = () => {
setIsPlaying(playing)
}, [state])
useEffectOnce(() => {
// 用于显示 windows taskbar buttons
if (playerSnapshot.track?.id) {
window.ipcRenderer?.send(IpcChannels.Pause)
}
})
return <></>
}

View file

@ -11,7 +11,6 @@ export const enum IpcChannels {
DevDbExportJson = 'dev-db-export-json',
CacheCoverColor = 'cache-cover-color',
SetTrayTooltip = 'set-tray-tooltip',
SetTrayLikeState = 'set-tray-like-state',
// 准备三个播放相关channel, 为 mpris 预留接口
Play = 'play',
Pause = 'pause',
@ -41,9 +40,6 @@ export interface IpcChannelsParams {
[IpcChannels.SetTrayTooltip]: {
text: string
}
[IpcChannels.SetTrayLikeState]: {
isLiked: boolean
}
[IpcChannels.Play]: void
[IpcChannels.Pause]: void
[IpcChannels.PlayOrPause]: void
@ -68,7 +64,6 @@ export interface IpcChannelsReturns {
[IpcChannels.DevDbExportJson]: void
[IpcChannels.CacheCoverColor]: void
[IpcChannels.SetTrayTooltip]: void
[IpcChannels.SetTrayLikeState]: void
[IpcChannels.Play]: void
[IpcChannels.Pause]: void
[IpcChannels.PlayOrPause]: void