From a878875f83a135e43bcc31f21ca93baa965acada Mon Sep 17 00:00:00 2001 From: Gelaechter <30231932+gelaechter@users.noreply.github.com> Date: Wed, 24 May 2023 17:35:04 +0200 Subject: [PATCH] Add native titlebar & fix app restart for AppImages --- src/main/main.ts | 20 +++++++++++++--- src/renderer/components/scroll-area/index.tsx | 8 +++++-- .../hooks/use-fixed-table-header.tsx | 9 +++++--- .../features/home/routes/home-route.tsx | 4 +++- .../components/sidebar-play-queue.tsx | 9 ++++---- .../player/components/full-screen-player.tsx | 10 ++++++-- .../components/window/window-settings.tsx | 23 ++++++++++++++++++- .../sidebar/components/collapsed-sidebar.tsx | 2 +- .../features/sidebar/components/sidebar.tsx | 2 +- src/renderer/layouts/default-layout.tsx | 2 +- .../layouts/default-layout/main-content.tsx | 10 ++++++-- src/renderer/layouts/window-bar.tsx | 6 +++-- 12 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index 87674913..7d95d185 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -183,8 +183,12 @@ const createWindow = async () => { await installExtensions(); } + const nativeFrame = store.get('window_window_bar_style') === 'linux'; + store.set('window_has_frame', nativeFrame); + mainWindow = new BrowserWindow({ - frame: false, + autoHideMenuBar: nativeFrame, + frame: nativeFrame, height: 900, icon: getAssetPath('icon.png'), minHeight: 600, @@ -229,8 +233,18 @@ const createWindow = async () => { }); ipcMain.on('app-restart', () => { - app.relaunch(); - app.exit(0); + // Fix for .AppImage + if (process.env.APPIMAGE) { + app.exit(); + app.relaunch({ + args: process.argv.slice(1).concat(['--appimage-extract-and-run']), + execPath: process.env.APPIMAGE, + }); + app.exit(0); + } else { + app.relaunch(); + app.exit(0); + } }); ipcMain.on('global-media-keys-enable', () => { diff --git a/src/renderer/components/scroll-area/index.tsx b/src/renderer/components/scroll-area/index.tsx index db3a414e..ccb705c4 100644 --- a/src/renderer/components/scroll-area/index.tsx +++ b/src/renderer/components/scroll-area/index.tsx @@ -34,12 +34,16 @@ const StyledNativeScrollArea = styled.div<{ scrollBarOffset?: string; windowBarS &::-webkit-scrollbar-track { margin-top: ${(props) => - props.windowBarStyle !== Platform.WEB ? '0px' : props.scrollBarOffset || '65px'}; + props.windowBarStyle === Platform.WINDOWS || props.windowBarStyle === Platform.MACOS + ? '0px' + : props.scrollBarOffset || '65px'}; } &::-webkit-scrollbar-thumb { margin-top: ${(props) => - props.windowBarStyle !== Platform.WEB ? '0px' : props.scrollBarOffset || '65px'}; + props.windowBarStyle === Platform.WINDOWS || props.windowBarStyle === Platform.MACOS + ? '0px' + : props.scrollBarOffset || '65px'}; } `; diff --git a/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx b/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx index b645b939..eaa829c2 100644 --- a/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx +++ b/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx @@ -9,7 +9,10 @@ export const useFixedTableHeader = () => { const { windowBarStyle } = useWindowSettings(); const isNotPastTableIntersection = useInView(intersectRef, { - margin: windowBarStyle === Platform.WEB ? '-68px 0px 0px 0px' : '-98px 0px 0px 0px', + margin: + windowBarStyle === Platform.WEB || windowBarStyle === Platform.LINUX + ? '-68px 0px 0px 0px' + : '-98px 0px 0px 0px', }); const tableInView = useInView(tableContainerRef, { @@ -21,13 +24,13 @@ export const useFixedTableHeader = () => { const root = document.querySelector('main .ag-root'); if (isNotPastTableIntersection || !tableInView) { - if (windowBarStyle !== Platform.WEB) { + if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { header?.classList.remove('window-frame'); } header?.classList.remove('ag-header-fixed'); root?.classList.remove('ag-header-fixed-margin'); } else { - if (windowBarStyle !== Platform.WEB) { + if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { header?.classList.add('window-frame'); } header?.classList.add('ag-header-fixed'); diff --git a/src/renderer/features/home/routes/home-route.tsx b/src/renderer/features/home/routes/home-route.tsx index 9d98c4e5..7978825e 100644 --- a/src/renderer/features/home/routes/home-route.tsx +++ b/src/renderer/features/home/routes/home-route.tsx @@ -138,7 +138,9 @@ const HomeRoute = () => { diff --git a/src/renderer/features/now-playing/components/sidebar-play-queue.tsx b/src/renderer/features/now-playing/components/sidebar-play-queue.tsx index c213563c..0de8d534 100644 --- a/src/renderer/features/now-playing/components/sidebar-play-queue.tsx +++ b/src/renderer/features/now-playing/components/sidebar-play-queue.tsx @@ -13,16 +13,17 @@ export const SidebarPlayQueue = () => { const queueRef = useRef<{ grid: AgGridReactType } | null>(null); const { windowBarStyle } = useWindowSettings(); + const webOrNative = windowBarStyle === Platform.WEB || windowBarStyle === Platform.LINUX; return ( - {windowBarStyle === Platform.WEB && ( - + {webOrNative && ( + )} { const { windowBarStyle } = custom; return { - height: windowBarStyle !== Platform.WEB ? 'calc(100vh - 120px)' : 'calc(100vh - 90px)', + height: + windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS + ? 'calc(100vh - 120px)' + : 'calc(100vh - 90px)', position: 'absolute', top: '100vh', transition: { @@ -144,7 +147,10 @@ const containerVariants: Variants = { const { dynamicBackground, background, windowBarStyle } = custom; return { background: dynamicBackground ? background : 'var(--main-bg)', - height: windowBarStyle !== Platform.WEB ? 'calc(100vh - 120px)' : 'calc(100vh - 90px)', + height: + windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS + ? 'calc(100vh - 120px)' + : 'calc(100vh - 90px)', left: 0, position: 'absolute', top: 0, diff --git a/src/renderer/features/settings/components/window/window-settings.tsx b/src/renderer/features/settings/components/window/window-settings.tsx index 620eb9e1..c4d8b8d4 100644 --- a/src/renderer/features/settings/components/window/window-settings.tsx +++ b/src/renderer/features/settings/components/window/window-settings.tsx @@ -5,12 +5,13 @@ import { SettingsSection, SettingOption, } from '/@/renderer/features/settings/components/settings-section'; -import { Select, Switch } from '/@/renderer/components'; +import { Select, Switch, toast } from '/@/renderer/components'; const WINDOW_BAR_OPTIONS = [ { label: 'Web (hidden)', value: Platform.WEB }, { label: 'Windows', value: Platform.WINDOWS }, { label: 'macOS', value: Platform.MACOS }, + { label: 'Native', value: Platform.LINUX }, ]; const localSettings = isElectron() ? window.electron.localSettings : null; @@ -28,6 +29,26 @@ export const WindowSettings = () => { value={settings.windowBarStyle} onChange={(e) => { if (!e) return; + + // warn that a restart is required + if ( + (localSettings?.get('window_has_frame') && e !== Platform.LINUX) || + (!localSettings?.get('window_has_frame') && e === Platform.LINUX) + ) { + toast.info({ + autoClose: false, + id: 'restart-toast', + message: 'Restart to apply changes... close the notification to restart Feishin', + onClose: () => { + window.electron.ipc.send('app-restart'); + }, + title: 'Restart required', + }); + } else { + toast.update({ autoClose: 0, id: 'restart-toast', message: '', onClose: () => {} }); // clean old toasts + } + + localSettings?.set('window_window_bar_style', e as Platform); setSettings({ window: { ...settings, diff --git a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx index 3026dc8a..73f8b9df 100644 --- a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx +++ b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx @@ -34,7 +34,7 @@ const SidebarContainer = styled(motion.div)<{ windowBarStyle: Platform }>` flex-direction: column; height: 100%; max-height: ${(props) => - props.windowBarStyle === Platform.WEB + props.windowBarStyle === Platform.WEB || props.windowBarStyle === Platform.LINUX ? 'calc(100vh - 149px)' : 'calc(100vh - 119px)'}; // Playerbar (90px), titlebar (65px), windowbar (30px) user-select: none; diff --git a/src/renderer/features/sidebar/components/sidebar.tsx b/src/renderer/features/sidebar/components/sidebar.tsx index ea8f6e2a..a5743b3e 100644 --- a/src/renderer/features/sidebar/components/sidebar.tsx +++ b/src/renderer/features/sidebar/components/sidebar.tsx @@ -45,7 +45,7 @@ import { useWindowSettings } from '../../../store/settings.store'; const SidebarContainer = styled.div<{ windowBarStyle: Platform }>` height: 100%; max-height: ${(props) => - props.windowBarStyle === Platform.WEB + props.windowBarStyle === Platform.WEB || props.windowBarStyle === Platform.LINUX ? 'calc(100vh - 149px)' : 'calc(100vh - 179px)'}; // Playerbar (90px), titlebar (65px), windowbar (30px) user-select: none; diff --git a/src/renderer/layouts/default-layout.tsx b/src/renderer/layouts/default-layout.tsx index caf076d7..bd55d736 100644 --- a/src/renderer/layouts/default-layout.tsx +++ b/src/renderer/layouts/default-layout.tsx @@ -29,7 +29,7 @@ const Layout = styled.div<{ windowBarStyle: Platform }>` 'main-content' 'player'; grid-template-rows: ${(props) => - props.windowBarStyle !== Platform.WEB + props.windowBarStyle === Platform.WINDOWS || props.windowBarStyle === Platform.MACOS ? '30px calc(100vh - 120px) 90px' : '0px calc(100vh - 90px) 90px'}; grid-template-columns: 1fr; diff --git a/src/renderer/layouts/default-layout/main-content.tsx b/src/renderer/layouts/default-layout/main-content.tsx index 8952bf89..6acd1233 100644 --- a/src/renderer/layouts/default-layout/main-content.tsx +++ b/src/renderer/layouts/default-layout/main-content.tsx @@ -104,7 +104,10 @@ const QueueDrawerArea = styled(motion.div)` const queueDrawerVariants: Variants = { closed: (windowBarStyle) => ({ - height: windowBarStyle !== Platform.WEB ? 'calc(100vh - 205px)' : 'calc(100vh - 175px)', + height: + windowBarStyle === Platform.WINDOWS || Platform.MACOS + ? 'calc(100vh - 205px)' + : 'calc(100vh - 175px)', position: 'absolute', right: 0, top: '75px', @@ -117,7 +120,10 @@ const queueDrawerVariants: Variants = { }), open: (windowBarStyle) => ({ boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.8)', - height: windowBarStyle !== Platform.WEB ? 'calc(100vh - 205px)' : 'calc(100vh - 175px)', + height: + windowBarStyle === Platform.WINDOWS || Platform.MACOS + ? 'calc(100vh - 205px)' + : 'calc(100vh - 175px)', position: 'absolute', right: '20px', top: '75px', diff --git a/src/renderer/layouts/window-bar.tsx b/src/renderer/layouts/window-bar.tsx index 0b595467..399ad7bb 100644 --- a/src/renderer/layouts/window-bar.tsx +++ b/src/renderer/layouts/window-bar.tsx @@ -219,6 +219,7 @@ export const WindowBar = () => { const statusString = playerStatus === PlayerStatus.PAUSED ? '(Paused) ' : ''; const queueString = length ? `(${index + 1} / ${length}) ` : ''; const title = length ? `${statusString}${queueString}${currentSong?.name}` : 'Feishin'; + document.title = title; const [max, setMax] = useState(false); @@ -237,12 +238,13 @@ export const WindowBar = () => { return ( <> - {windowBarStyle === Platform.WINDOWS ? ( + {windowBarStyle === Platform.WINDOWS && ( - ) : ( + )} + {windowBarStyle === Platform.MACOS && (