mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 09:41:49 +08:00
feat(components/Navbar): 自訂和微調各系統的 titlebar (#1343)
* feat: linux custom titlebar * add settings init * Update zh-TW.js * fix: color Co-authored-by: memorydream <34763046+memorydream@users.noreply.github.com>
This commit is contained in:
parent
3e1dc62fa0
commit
3d5d40c476
BIN
public/img/logos/yesplaymusic-white24x24.png
Normal file
BIN
public/img/logos/yesplaymusic-white24x24.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 750 B |
|
@ -180,7 +180,10 @@ class Background {
|
|||
minWidth: 1080,
|
||||
minHeight: 720,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
frame: !isWindows,
|
||||
frame: !(
|
||||
isWindows ||
|
||||
(isLinux && this.store.get('settings.linuxEnableCustomTitlebar'))
|
||||
),
|
||||
title: 'YesPlayMusic',
|
||||
show: false,
|
||||
webPreferences: {
|
||||
|
|
132
src/components/LinuxTitlebar.vue
Normal file
132
src/components/LinuxTitlebar.vue
Normal file
|
@ -0,0 +1,132 @@
|
|||
<template>
|
||||
<div class="linux-titlebar">
|
||||
<div class="logo">
|
||||
<img src="img/logos/yesplaymusic-white24x24.png" />
|
||||
</div>
|
||||
<div class="title">{{ title }}</div>
|
||||
<div class="controls">
|
||||
<div
|
||||
class="button minimize codicon codicon-chrome-minimize"
|
||||
@click="windowMinimize"
|
||||
></div>
|
||||
<div
|
||||
class="button max-restore codicon"
|
||||
:class="{
|
||||
'codicon-chrome-restore': !isShowMaximized,
|
||||
'codicon-chrome-maximize': isShowMaximized,
|
||||
}"
|
||||
@click="windowMaxRestore"
|
||||
></div>
|
||||
<div
|
||||
class="button close codicon codicon-chrome-close"
|
||||
@click="windowClose"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// icons by https://github.com/microsoft/vscode-codicons
|
||||
import 'vscode-codicons/dist/codicon.css';
|
||||
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||
const ipcRenderer =
|
||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||
|
||||
export default {
|
||||
name: 'LinuxTitlebar',
|
||||
data() {
|
||||
return {
|
||||
isShowMaximized: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['title']),
|
||||
},
|
||||
created() {
|
||||
if (process.env.IS_ELECTRON === true) {
|
||||
ipcRenderer.on('isMaximized', (_, value) => {
|
||||
// 当窗口最大化时,value为false
|
||||
// 当窗口还原时,value为true
|
||||
this.isShowMaximized = value;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
windowMinimize() {
|
||||
ipcRenderer.send('minimize');
|
||||
},
|
||||
windowMaxRestore() {
|
||||
ipcRenderer.send('maximizeOrUnmaximize');
|
||||
},
|
||||
windowClose() {
|
||||
ipcRenderer.send('close');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.linux-titlebar {
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
--hover: #e6e6e6;
|
||||
--active: #cccccc;
|
||||
|
||||
.logo {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
font-family: 'Segoe UI', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
|
||||
justify-self: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.controls {
|
||||
height: 32px;
|
||||
//margin-left: auto;
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
.button {
|
||||
height: 100%;
|
||||
width: 46px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
-webkit-app-region: no-drag;
|
||||
&:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
&:active {
|
||||
background: var(--active);
|
||||
}
|
||||
&.close {
|
||||
&:hover {
|
||||
background: #c42c1b;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
&:active {
|
||||
background: #f1707a;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-theme='dark'] .linux-titlebar {
|
||||
--hover: #191919;
|
||||
--active: #333333;
|
||||
}
|
||||
</style>
|
|
@ -1,27 +1,8 @@
|
|||
<template>
|
||||
<div>
|
||||
<nav>
|
||||
<div class="win32-titlebar">
|
||||
<div class="title">YesPlayMusic</div>
|
||||
<div class="controls">
|
||||
<div
|
||||
class="button minimize codicon codicon-chrome-minimize"
|
||||
@click="windowMinimize"
|
||||
></div>
|
||||
<div
|
||||
class="button max-restore codicon"
|
||||
:class="{
|
||||
'codicon-chrome-restore': !isWindowMaximized,
|
||||
'codicon-chrome-maximize': isWindowMaximized,
|
||||
}"
|
||||
@click="windowMaxRestore"
|
||||
></div>
|
||||
<div
|
||||
class="button close codicon codicon-chrome-close"
|
||||
@click="windowClose"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<nav :class="{ 'has-custom-titlebar': hasCustomTitlebar }">
|
||||
<Win32Titlebar v-if="enableWin32Titlebar" />
|
||||
<LinuxTitlebar v-if="enableLinuxTitlebar" />
|
||||
<div class="navigation-buttons">
|
||||
<button-icon @click.native="go('back')"
|
||||
><svg-icon icon-class="arrow-left"
|
||||
|
@ -96,17 +77,16 @@ import { isLooseLoggedIn, doLogout } from '@/utils/auth';
|
|||
// icons by https://github.com/microsoft/vscode-codicons
|
||||
import 'vscode-codicons/dist/codicon.css';
|
||||
|
||||
import Win32Titlebar from '@/components/Win32Titlebar.vue';
|
||||
import LinuxTitlebar from '@/components/LinuxTitlebar.vue';
|
||||
import ContextMenu from '@/components/ContextMenu.vue';
|
||||
import ButtonIcon from '@/components/ButtonIcon.vue';
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||
const ipcRenderer =
|
||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||
|
||||
export default {
|
||||
name: 'Navbar',
|
||||
components: {
|
||||
Win32Titlebar,
|
||||
LinuxTitlebar,
|
||||
ButtonIcon,
|
||||
ContextMenu,
|
||||
},
|
||||
|
@ -115,7 +95,8 @@ export default {
|
|||
inputFocus: false,
|
||||
langs: ['zh-CN', 'zh-TW', 'en', 'tr'],
|
||||
keywords: '',
|
||||
isWindowMaximized: false,
|
||||
enableWin32Titlebar: false,
|
||||
enableLinuxTitlebar: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -128,12 +109,18 @@ export default {
|
|||
? `${this.data?.user?.avatarUrl}?param=512y512`
|
||||
: 'http://s4.music.126.net/style/web2/img/default/default_avatar.jpg?param=60y60';
|
||||
},
|
||||
hasCustomTitlebar() {
|
||||
return this.enableWin32Titlebar || this.enableLinuxTitlebar;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (process.env.IS_ELECTRON === true) {
|
||||
ipcRenderer.on('isMaximized', (event, value) => {
|
||||
this.isWindowMaximized = value;
|
||||
});
|
||||
if (process.platform === 'win32') {
|
||||
this.enableWin32Titlebar = true;
|
||||
} else if (
|
||||
process.platform === 'linux' &&
|
||||
this.settings.linuxEnableCustomTitlebar
|
||||
) {
|
||||
this.enableLinuxTitlebar = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -175,15 +162,6 @@ export default {
|
|||
this.$router.push({ name: 'login' });
|
||||
}
|
||||
},
|
||||
windowMinimize() {
|
||||
ipcRenderer.send('minimize');
|
||||
},
|
||||
windowMaxRestore() {
|
||||
ipcRenderer.send('maximizeOrUnmaximize');
|
||||
},
|
||||
windowClose() {
|
||||
ipcRenderer.send('close');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -221,68 +199,9 @@ nav {
|
|||
}
|
||||
}
|
||||
|
||||
.win32-titlebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-electron-os='win32'] {
|
||||
nav {
|
||||
padding-top: 20px;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
.win32-titlebar {
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
--hover: #e6e6e6;
|
||||
--active: #cccccc;
|
||||
|
||||
.title {
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
font-family: 'Segoe UI', 'Microsoft YaHei UI', 'Microsoft YaHei',
|
||||
sans-serif;
|
||||
}
|
||||
.controls {
|
||||
height: 32px;
|
||||
margin-left: auto;
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
.button {
|
||||
height: 100%;
|
||||
width: 46px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
-webkit-app-region: no-drag;
|
||||
&:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
&:active {
|
||||
background: var(--active);
|
||||
}
|
||||
&.close {
|
||||
&:hover {
|
||||
background: rgba(232, 17, 35, 0.9);
|
||||
}
|
||||
&:active {
|
||||
background: #f1707a;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&[data-theme='dark'] .win32-titlebar {
|
||||
--hover: #191919;
|
||||
--active: #333333;
|
||||
}
|
||||
nav.has-custom-titlebar {
|
||||
padding-top: 20px;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.navigation-buttons {
|
||||
|
|
123
src/components/Win32Titlebar.vue
Normal file
123
src/components/Win32Titlebar.vue
Normal file
|
@ -0,0 +1,123 @@
|
|||
<template>
|
||||
<div class="win32-titlebar">
|
||||
<div class="title">{{ title }}</div>
|
||||
<div class="controls">
|
||||
<div
|
||||
class="button minimize codicon codicon-chrome-minimize"
|
||||
@click="windowMinimize"
|
||||
></div>
|
||||
<div
|
||||
class="button max-restore codicon"
|
||||
:class="{
|
||||
'codicon-chrome-restore': !isShowMaximized,
|
||||
'codicon-chrome-maximize': isShowMaximized,
|
||||
}"
|
||||
@click="windowMaxRestore"
|
||||
></div>
|
||||
<div
|
||||
class="button close codicon codicon-chrome-close"
|
||||
@click="windowClose"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// icons by https://github.com/microsoft/vscode-codicons
|
||||
import 'vscode-codicons/dist/codicon.css';
|
||||
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
const electron =
|
||||
process.env.IS_ELECTRON === true ? window.require('electron') : null;
|
||||
const ipcRenderer =
|
||||
process.env.IS_ELECTRON === true ? electron.ipcRenderer : null;
|
||||
|
||||
export default {
|
||||
name: 'Win32Titlebar',
|
||||
data() {
|
||||
return {
|
||||
isShowMaximized: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['title']),
|
||||
},
|
||||
created() {
|
||||
if (process.env.IS_ELECTRON === true) {
|
||||
ipcRenderer.on('isMaximized', (_, value) => {
|
||||
// 当窗口最大化时,value为false
|
||||
// 当窗口还原时,value为true
|
||||
this.isShowMaximized = value;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
windowMinimize() {
|
||||
ipcRenderer.send('minimize');
|
||||
},
|
||||
windowMaxRestore() {
|
||||
ipcRenderer.send('maximizeOrUnmaximize');
|
||||
},
|
||||
windowClose() {
|
||||
ipcRenderer.send('close');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.win32-titlebar {
|
||||
color: var(--color-text);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-app-region: drag;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
--hover: #e6e6e6;
|
||||
--active: #cccccc;
|
||||
|
||||
.title {
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
font-family: 'Segoe UI', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
|
||||
}
|
||||
.controls {
|
||||
height: 32px;
|
||||
margin-left: auto;
|
||||
justify-content: flex-end;
|
||||
display: flex;
|
||||
.button {
|
||||
height: 100%;
|
||||
width: 46px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
-webkit-app-region: no-drag;
|
||||
&:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
&:active {
|
||||
background: var(--active);
|
||||
}
|
||||
&.close {
|
||||
&:hover {
|
||||
background: #c42c1b;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
&:active {
|
||||
background: #f1707a;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-theme='dark'] .win32-titlebar {
|
||||
--hover: #191919;
|
||||
--active: #333333;
|
||||
}
|
||||
</style>
|
|
@ -158,6 +158,7 @@ export default {
|
|||
showLibraryDefault: 'Show Library after App Launched',
|
||||
subTitleDefault: 'Show Alias for Subtitle by default',
|
||||
enableReversedMode: 'Enable Reversed Mode (Experimental)',
|
||||
enableCustomTitlebar: 'Enable custom title bar (Need restart)',
|
||||
lyricsBackground: {
|
||||
text: 'Show Lyrics Background',
|
||||
off: 'Off',
|
||||
|
|
|
@ -150,7 +150,9 @@ export default {
|
|||
showPlaylistsByAppleMusic: "Apple Music'in Çalma Listelerini Göster",
|
||||
enableDiscordRichPresence: 'Discord gösterimini aktifleştir',
|
||||
showLibraryDefault: 'Kitaplık Varsayılanını göster',
|
||||
subTitleDefault: 'Sub title alia default',
|
||||
subTitleDefault: 'Show Alias for Subtitle by default',
|
||||
enableReversedMode: 'Enable Reversed Mode (Experimental)',
|
||||
enableCustomTitlebar: 'Enable custom title bar (Need restart)',
|
||||
lyricsBackground: {
|
||||
text: 'Şarkı Sözleri Arka Planını Göster',
|
||||
off: 'kapalı',
|
||||
|
|
|
@ -159,6 +159,7 @@ export default {
|
|||
showLibraryDefault: '启动后显示音乐库',
|
||||
subTitleDefault: '副标题使用别名',
|
||||
enableReversedMode: '启用倒序播放功能 (实验性功能)',
|
||||
enableCustomTitlebar: '启用自定义标题栏 (重启后生效)',
|
||||
lyricsBackground: {
|
||||
text: '显示歌词背景',
|
||||
off: '关闭',
|
||||
|
|
|
@ -156,6 +156,7 @@ export default {
|
|||
showLibraryDefault: '啟動後顯示音樂庫',
|
||||
subTitleDefault: '副標題使用別名',
|
||||
enableReversedMode: '啟用倒序播放功能 (實驗性功能)',
|
||||
enableCustomTitlebar: '啟用自訂標題列(重新啟動後生效)',
|
||||
lyricsBackground: {
|
||||
text: '顯示歌詞背景',
|
||||
off: '關閉',
|
||||
|
|
|
@ -28,6 +28,7 @@ let localStorage = {
|
|||
enableGlobalShortcut: true,
|
||||
showLibraryDefault: false,
|
||||
subTitleDefault: false,
|
||||
linuxEnableCustomTitlebar: false,
|
||||
enabledPlaylistCategories,
|
||||
proxyConfig: {
|
||||
protocol: 'noProxy',
|
||||
|
|
|
@ -72,4 +72,7 @@ export default {
|
|||
enableScrolling(state, status = null) {
|
||||
state.enableScrolling = status ? status : !state.enableScrolling;
|
||||
},
|
||||
updateTitle(state, title) {
|
||||
state.title = title;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ updateApp();
|
|||
export default {
|
||||
showLyrics: false,
|
||||
enableScrolling: true,
|
||||
title: 'YesPlayMusic',
|
||||
liked: {
|
||||
songs: [],
|
||||
songsWithDetails: [], // 只有前12首
|
||||
|
|
|
@ -34,6 +34,7 @@ function setTitle(track) {
|
|||
if (isCreateTray) {
|
||||
ipcRenderer.send('updateTrayTooltip', document.title);
|
||||
}
|
||||
store.commit('updateTitle', document.title);
|
||||
}
|
||||
|
||||
function setTrayLikeState(isLiked) {
|
||||
|
|
|
@ -331,6 +331,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isElectron && isLinux" class="item">
|
||||
<div class="left">
|
||||
<div class="title"> {{ $t('settings.enableCustomTitlebar') }} </div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="toggle">
|
||||
<input
|
||||
id="enable-custom-titlebar"
|
||||
v-model="enableCustomTitlebar"
|
||||
type="checkbox"
|
||||
name="enable-custom-titlebar"
|
||||
/>
|
||||
<label for="enable-custom-titlebar"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isElectron" class="item">
|
||||
<div class="left">
|
||||
<div class="title"> {{ $t('settings.showLibraryDefault') }}</div>
|
||||
|
@ -592,6 +609,9 @@ export default {
|
|||
isMac() {
|
||||
return /macintosh|mac os x/i.test(navigator.userAgent);
|
||||
},
|
||||
isLinux() {
|
||||
return process.platform === 'linux';
|
||||
},
|
||||
version() {
|
||||
return pkg.version;
|
||||
},
|
||||
|
@ -928,6 +948,17 @@ export default {
|
|||
});
|
||||
},
|
||||
},
|
||||
enableCustomTitlebar: {
|
||||
get() {
|
||||
return this.settings.linuxEnableCustomTitlebar;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('updateSettings', {
|
||||
key: 'linuxEnableCustomTitlebar',
|
||||
value,
|
||||
});
|
||||
},
|
||||
},
|
||||
isLastfmConnected() {
|
||||
return this.lastfm.key !== undefined;
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user