diff --git a/src/RootAppRouter.tsx b/src/RootAppRouter.tsx index bed7a9e4a0..37d3cca651 100644 --- a/src/RootAppRouter.tsx +++ b/src/RootAppRouter.tsx @@ -17,7 +17,7 @@ import { createRouterHistory } from 'components/router/routerHistory'; import UserThemeProvider from 'themes/UserThemeProvider'; const layoutMode = localStorage.getItem('layout'); -const isExperimentalLayout = layoutMode === 'experimental'; +const isExperimentalLayout = layoutMode === 'experimental' || !layoutMode; const router = createHashRouter([ { diff --git a/src/apps/dashboard/AppLayout.tsx b/src/apps/dashboard/AppLayout.tsx index 44b8ad2caf..26db00d0e8 100644 --- a/src/apps/dashboard/AppLayout.tsx +++ b/src/apps/dashboard/AppLayout.tsx @@ -9,6 +9,7 @@ import { Outlet, useLocation } from 'react-router-dom'; import AppBody from 'components/AppBody'; import AppToolbar from 'components/toolbar/AppToolbar'; +import ServerButton from 'components/toolbar/ServerButton'; import ElevationScroll from 'components/ElevationScroll'; import { DRAWER_WIDTH } from 'components/ResponsiveDrawer'; import ThemeCss from 'components/ThemeCss'; @@ -22,8 +23,6 @@ import { DASHBOARD_APP_PATHS } from './routes/routes'; import './AppOverrides.scss'; -const DRAWERLESS_PATHS = [ DASHBOARD_APP_PATHS.MetadataManager ]; - export const Component: FC = () => { const [ isDrawerActive, setIsDrawerActive ] = useState(false); const location = useLocation(); @@ -31,8 +30,8 @@ export const Component: FC = () => { const { dateFnsLocale } = useLocale(); const isMediumScreen = useMediaQuery((t: Theme) => t.breakpoints.up('md')); - const isDrawerAvailable = Boolean(user) - && !DRAWERLESS_PATHS.some(path => location.pathname.startsWith(`/${path}`)); + const isMetadataManager = location.pathname.startsWith(`/${DASHBOARD_APP_PATHS.MetadataManager}`); + const isDrawerAvailable = Boolean(user) && !isMetadataManager; const isDrawerOpen = isDrawerActive && isDrawerAvailable; const onToggleDrawer = useCallback(() => { @@ -74,6 +73,10 @@ export const Component: FC = () => { } > + {isMetadataManager && ( + + )} + diff --git a/src/apps/experimental/AppLayout.tsx b/src/apps/experimental/AppLayout.tsx index 6412115302..8d5e04ed8f 100644 --- a/src/apps/experimental/AppLayout.tsx +++ b/src/apps/experimental/AppLayout.tsx @@ -8,7 +8,6 @@ import { Outlet, useLocation } from 'react-router-dom'; import AppBody from 'components/AppBody'; import CustomCss from 'components/CustomCss'; import ElevationScroll from 'components/ElevationScroll'; -import { DRAWER_WIDTH } from 'components/ResponsiveDrawer'; import ThemeCss from 'components/ThemeCss'; import { useApi } from 'hooks/useApi'; @@ -23,7 +22,7 @@ export const Component = () => { const location = useLocation(); const isMediumScreen = useMediaQuery((t: Theme) => t.breakpoints.up('md')); - const isDrawerAvailable = isDrawerPath(location.pathname) && Boolean(user); + const isDrawerAvailable = isDrawerPath(location.pathname) && Boolean(user) && !isMediumScreen; const isDrawerOpen = isDrawerActive && isDrawerAvailable; const onToggleDrawer = useCallback(() => { @@ -38,14 +37,8 @@ export const Component = () => { { return params; }; -interface SearchButtonProps { - isTabsAvailable: boolean; -} - -const SearchButton: FC = ({ isTabsAvailable }) => { +const SearchButton: FC = () => { const location = useLocation(); const [searchParams] = useSearchParams(); const isSearchPath = location.pathname === '/search'; - const createSearchLink = isTabsAvailable ? + const search = createSearchParams(getUrlParams(searchParams)); + const createSearchLink = { pathname: '/search', - search: `?${createSearchParams(getUrlParams(searchParams))}` - } : - '/search'; + search: search ? `?${search}` : undefined + }; return ( diff --git a/src/apps/experimental/components/AppToolbar/index.tsx b/src/apps/experimental/components/AppToolbar/index.tsx index df46cc1233..308b96826a 100644 --- a/src/apps/experimental/components/AppToolbar/index.tsx +++ b/src/apps/experimental/components/AppToolbar/index.tsx @@ -1,11 +1,14 @@ +import Stack from '@mui/material/Stack'; import React, { type FC } from 'react'; import { useLocation } from 'react-router-dom'; + import AppToolbar from 'components/toolbar/AppToolbar'; -import AppTabs from '../tabs/AppTabs'; +import ServerButton from 'components/toolbar/ServerButton'; + import RemotePlayButton from './RemotePlayButton'; import SyncPlayButton from './SyncPlayButton'; import SearchButton from './SearchButton'; -import { isTabPath } from '../tabs/tabRoutes'; +import UserViewNav from './userViews/UserViewNav'; interface AppToolbarProps { isDrawerAvailable: boolean @@ -31,7 +34,6 @@ const ExperimentalAppToolbar: FC = ({ // The video osd does not show the standard toolbar if (location.pathname === '/video') return null; - const isTabsAvailable = isTabPath(location.pathname); const isPublicPath = PUBLIC_PATHS.includes(location.pathname); return ( @@ -40,7 +42,7 @@ const ExperimentalAppToolbar: FC = ({ <> - + )} isDrawerAvailable={isDrawerAvailable} @@ -48,7 +50,18 @@ const ExperimentalAppToolbar: FC = ({ onDrawerButtonClick={onDrawerButtonClick} isUserMenuAvailable={!isPublicPath} > - {isTabsAvailable && ()} + {!isDrawerAvailable && ( + + + + {!isPublicPath && ( + + )} + + )} ); }; diff --git a/src/apps/experimental/components/AppToolbar/userViews/UserViewNav.tsx b/src/apps/experimental/components/AppToolbar/userViews/UserViewNav.tsx new file mode 100644 index 0000000000..351f95fcc9 --- /dev/null +++ b/src/apps/experimental/components/AppToolbar/userViews/UserViewNav.tsx @@ -0,0 +1,150 @@ +import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto'; +import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type'; +import ArrowDropDown from '@mui/icons-material/ArrowDropDown'; +import Favorite from '@mui/icons-material/Favorite'; +import Button from '@mui/material/Button/Button'; +import { Theme } from '@mui/material/styles'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import React, { useCallback, useMemo, useState } from 'react'; +import { Link, useLocation, useSearchParams } from 'react-router-dom'; + +import LibraryIcon from 'apps/experimental/components/LibraryIcon'; +import { isTabPath } from 'apps/experimental/components/tabs/tabRoutes'; +import { PseudoUserViews } from 'apps/experimental/constants/PseudoUserViews'; +import { appRouter } from 'components/router/appRouter'; +import { useApi } from 'hooks/useApi'; +import useCurrentTab from 'hooks/useCurrentTab'; +import { useUserViews } from 'hooks/useUserViews'; +import globalize from 'lib/globalize'; + +import UserViewsMenu from './UserViewsMenu'; + +const MAX_USER_VIEWS_MD = 3; +const MAX_USER_VIEWS_LG = 5; +const MAX_USER_VIEWS_XL = 8; + +const OVERFLOW_MENU_ID = 'user-view-overflow-menu'; + +const HOME_PATH = '/home'; +const LIST_PATH = '/list'; + +const getCurrentUserView = ( + userViews: BaseItemDto[] | undefined, + pathname: string, + libraryId: string | null, + collectionType: string | null, + tab: number +) => { + const isUserViewPath = isTabPath(pathname) || [HOME_PATH, LIST_PATH].includes(pathname); + if (!isUserViewPath) return undefined; + + if (collectionType === CollectionType.Livetv) { + return userViews?.find(({ CollectionType: type }) => type === CollectionType.Livetv); + } + + if (pathname === HOME_PATH && tab === 1) { + return PseudoUserViews.Favorites; + } + + // eslint-disable-next-line sonarjs/different-types-comparison + return userViews?.find(({ Id: id }) => id === libraryId); +}; + +const UserViewNav = () => { + const location = useLocation(); + const [ searchParams ] = useSearchParams(); + const libraryId = searchParams.get('topParentId') || searchParams.get('parentId'); + const collectionType = searchParams.get('collectionType'); + const { activeTab } = useCurrentTab(); + + const isExtraLargeScreen = useMediaQuery((t: Theme) => t.breakpoints.up('xl')); + const isLargeScreen = useMediaQuery((t: Theme) => t.breakpoints.up('lg')); + const maxViews = useMemo(() => { + if (isExtraLargeScreen) return MAX_USER_VIEWS_XL; + if (isLargeScreen) return MAX_USER_VIEWS_LG; + return MAX_USER_VIEWS_MD; + }, [ isExtraLargeScreen, isLargeScreen ]); + + const { user } = useApi(); + const { + data: userViews, + isPending + } = useUserViews(user?.Id); + + const primaryViews = useMemo(() => ( + userViews?.Items?.slice(0, maxViews) + ), [ maxViews, userViews ]); + + const overflowViews = useMemo(() => ( + userViews?.Items?.slice(maxViews) + ), [ maxViews, userViews ]); + + const [ overflowAnchorEl, setOverflowAnchorEl ] = useState(null); + const isOverflowMenuOpen = Boolean(overflowAnchorEl); + + const onOverflowButtonClick = useCallback((event: React.MouseEvent) => { + setOverflowAnchorEl(event.currentTarget); + }, []); + + const onOverflowMenuClose = useCallback(() => { + setOverflowAnchorEl(null); + }, []); + + const currentUserView = useMemo(() => ( + getCurrentUserView(userViews?.Items, location.pathname, libraryId, collectionType, activeTab) + ), [ activeTab, collectionType, libraryId, location.pathname, userViews ]); + + if (isPending) return null; + + return ( + <> + + + {primaryViews?.map(view => ( + + ))} + {overflowViews && overflowViews.length > 0 && ( + <> + + + + + )} + + ); +}; + +export default UserViewNav; diff --git a/src/apps/experimental/components/AppToolbar/userViews/UserViewsMenu.tsx b/src/apps/experimental/components/AppToolbar/userViews/UserViewsMenu.tsx new file mode 100644 index 0000000000..e95617e741 --- /dev/null +++ b/src/apps/experimental/components/AppToolbar/userViews/UserViewsMenu.tsx @@ -0,0 +1,51 @@ +import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client'; +import ListItemIcon from '@mui/material/ListItemIcon/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText/ListItemText'; +import Menu, { type MenuProps } from '@mui/material/Menu/Menu'; +import MenuItem from '@mui/material/MenuItem/MenuItem'; +import React, { FC } from 'react'; +import { Link } from 'react-router-dom'; + +import LibraryIcon from 'apps/experimental/components/LibraryIcon'; +import { appRouter } from 'components/router/appRouter'; + +interface UserViewsMenuProps extends MenuProps { + userViews: BaseItemDto[] + selectedId?: string + includeGlobalViews?: boolean + onMenuClose: () => void +} + +const UserViewsMenu: FC = ({ + userViews, + selectedId, + onMenuClose, + ...props +}) => { + return ( + + {userViews.map(view => ( + + + + + + {view.Name} + + + ))} + + ); +}; + +export default UserViewsMenu; diff --git a/src/apps/experimental/components/LibraryIcon.tsx b/src/apps/experimental/components/LibraryIcon.tsx index 846e3f887c..6a5b2db61a 100644 --- a/src/apps/experimental/components/LibraryIcon.tsx +++ b/src/apps/experimental/components/LibraryIcon.tsx @@ -1,5 +1,6 @@ import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client'; import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type'; +import Favorite from '@mui/icons-material/Favorite'; import Movie from '@mui/icons-material/Movie'; import MusicNote from '@mui/icons-material/MusicNote'; import Photo from '@mui/icons-material/Photo'; @@ -14,6 +15,8 @@ import VideoLibrary from '@mui/icons-material/VideoLibrary'; import Folder from '@mui/icons-material/Folder'; import React, { FC } from 'react'; +import { PseudoUserViews } from '../constants/PseudoUserViews'; + interface LibraryIconProps { item: BaseItemDto } @@ -21,6 +24,10 @@ interface LibraryIconProps { const LibraryIcon: FC = ({ item }) => { + if (item.Id === PseudoUserViews.Favorites.Id) { + return ; + } + switch (item.CollectionType) { case CollectionType.Movies: return ; diff --git a/src/apps/experimental/components/drawers/MainDrawerContent.tsx b/src/apps/experimental/components/drawers/MainDrawerContent.tsx index e15b833616..b135694411 100644 --- a/src/apps/experimental/components/drawers/MainDrawerContent.tsx +++ b/src/apps/experimental/components/drawers/MainDrawerContent.tsx @@ -1,5 +1,3 @@ -import Dashboard from '@mui/icons-material/Dashboard'; -import Edit from '@mui/icons-material/Edit'; import Favorite from '@mui/icons-material/Favorite'; import Home from '@mui/icons-material/Home'; import Divider from '@mui/material/Divider'; @@ -111,38 +109,6 @@ const MainDrawerContent = () => { )} - - {/* ADMIN LINKS */} - {user?.Policy?.IsAdministrator && ( - <> - - - {globalize.translate('HeaderAdmin')} - - } - > - - - - - - - - - - - - - - - - - - - )} ); }; diff --git a/src/apps/experimental/components/library/ItemsView.tsx b/src/apps/experimental/components/library/ItemsView.tsx index dbe1753fd3..db6303324d 100644 --- a/src/apps/experimental/components/library/ItemsView.tsx +++ b/src/apps/experimental/components/library/ItemsView.tsx @@ -14,6 +14,15 @@ import { CardShape } from 'utils/card'; import Loading from 'components/loading/LoadingComponent'; import { playbackManager } from 'components/playback/playbackmanager'; import ItemsContainer from 'elements/emby-itemscontainer/ItemsContainer'; +import NoItemsMessage from 'components/common/NoItemsMessage'; +import Lists from 'components/listview/List/Lists'; +import Cards from 'components/cardbuilder/Card/Cards'; +import { LibraryTab } from 'types/libraryTab'; +import { type LibraryViewSettings, type ParentId, ViewMode } from 'types/library'; +import type { CardOptions } from 'types/cardOptions'; +import type { ListOptions } from 'types/listOptions'; +import { useItem } from 'hooks/useItem'; + import AlphabetPicker from './AlphabetPicker'; import FilterButton from './filter/FilterButton'; import NewCollectionButton from './NewCollectionButton'; @@ -23,14 +32,7 @@ import QueueButton from './QueueButton'; import ShuffleButton from './ShuffleButton'; import SortButton from './SortButton'; import GridListViewButton from './GridListViewButton'; -import NoItemsMessage from 'components/common/NoItemsMessage'; -import Lists from 'components/listview/List/Lists'; -import Cards from 'components/cardbuilder/Card/Cards'; -import { LibraryTab } from 'types/libraryTab'; -import { type LibraryViewSettings, type ParentId, ViewMode } from 'types/library'; -import type { CardOptions } from 'types/cardOptions'; -import type { ListOptions } from 'types/listOptions'; -import { useItem } from 'hooks/useItem'; +import LibraryViewMenu from './LibraryViewMenu'; interface ItemsViewProps { viewType: LibraryTab; @@ -225,17 +227,21 @@ const ItemsView: FC = ({ 'vertical-list' : 'vertical-wrap' ); + return ( - - {isPaginationEnabled && ( - + + + {isBtnPlayAllEnabled && ( = ({ libraryViewSettings={libraryViewSettings} /> )} + {isBtnShuffleEnabled && totalRecordCount > 1 && ( + + )} {isBtnQueueEnabled && item && playbackManager.canQueue(item) && ( @@ -255,15 +270,6 @@ const ItemsView: FC = ({ hasFilters={hasFilters} /> )} - {isBtnShuffleEnabled && totalRecordCount > 1 && ( - - )} {isBtnSortEnabled && ( = ({ setLibraryViewSettings={setLibraryViewSettings} /> )} + + {isPaginationEnabled && ( + + + + )} {isAlphabetPickerEnabled && hasSortName && ( @@ -312,7 +336,16 @@ const ItemsView: FC = ({ )} {isPaginationEnabled && ( - + { + const location = useLocation(); + const [ searchParams, setSearchParams ] = useSearchParams(); + const { activeTab } = useCurrentTab(); + + const [ menuAnchorEl, setMenuAnchorEl ] = useState(null); + const isMenuOpen = Boolean(menuAnchorEl); + + const onMenuButtonClick = useCallback((event: React.MouseEvent) => { + setMenuAnchorEl(event.currentTarget); + }, []); + + const onMenuClose = useCallback(() => { + setMenuAnchorEl(null); + }, []); + + const currentRoute = TabRoutes.find(({ path }) => path === location.pathname); + const currentTab = currentRoute?.tabs.find(({ index }) => index === activeTab); + + if (!currentTab) return null; + + return ( + <> + + + + {currentRoute?.tabs.map(tab => ( + { + searchParams.set('tab', `${tab.index}`); + setSearchParams(searchParams); + onMenuClose(); + }} + selected={tab.index === currentTab.index} + > + {globalize.translate(tab.label)} + + ))} + + + ); +}; + +export default LibraryViewMenu; diff --git a/src/apps/experimental/components/library/PageTabContent.tsx b/src/apps/experimental/components/library/PageTabContent.tsx index 6cd99c5575..10a0d22960 100644 --- a/src/apps/experimental/components/library/PageTabContent.tsx +++ b/src/apps/experimental/components/library/PageTabContent.tsx @@ -1,3 +1,4 @@ +import Box from '@mui/material/Box/Box'; import React, { type FC } from 'react'; import SuggestionsSectionView from './SuggestionsSectionView'; import UpcomingView from './UpcomingView'; @@ -8,6 +9,7 @@ import ProgramsSectionView from './ProgramsSectionView'; import { LibraryTab } from 'types/libraryTab'; import type { ParentId } from 'types/library'; import type { LibraryTabContent } from 'types/libraryTabContent'; +import LibraryViewMenu from './LibraryViewMenu'; interface PageTabContentProps { parentId: ParentId; @@ -17,46 +19,86 @@ interface PageTabContentProps { const PageTabContent: FC = ({ parentId, currentTab }) => { if (currentTab.viewType === LibraryTab.Suggestions) { return ( - + <> + + + + + + ); } if (currentTab.viewType === LibraryTab.Programs || currentTab.viewType === LibraryTab.Recordings || currentTab.viewType === LibraryTab.Schedule) { return ( - + <> + + + + + + ); } if (currentTab.viewType === LibraryTab.Upcoming) { - return ; + return ( + <> + + + + + + + ); } if (currentTab.viewType === LibraryTab.Genres) { return ( - + <> + + + + + + ); } if (currentTab.viewType === LibraryTab.Guide) { - return ; + return ( + <> + + + + + + + ); } return ( diff --git a/src/apps/experimental/components/library/Pagination.tsx b/src/apps/experimental/components/library/Pagination.tsx index ea3cd1cfe7..477a982312 100644 --- a/src/apps/experimental/components/library/Pagination.tsx +++ b/src/apps/experimental/components/library/Pagination.tsx @@ -47,10 +47,15 @@ const Pagination: FC = ({ }, [limit, setLibraryViewSettings, startIndex]); return ( - + {globalize.translate( diff --git a/src/apps/experimental/components/library/PlayAllButton.tsx b/src/apps/experimental/components/library/PlayAllButton.tsx index 9c87d0056b..b2c3da4181 100644 --- a/src/apps/experimental/components/library/PlayAllButton.tsx +++ b/src/apps/experimental/components/library/PlayAllButton.tsx @@ -51,6 +51,12 @@ const PlayAllButton: FC = ({ item, items, viewType, hasFilte title={globalize.translate('HeaderPlayAll')} className='paper-icon-button-light btnPlay autoSize' onClick={play} + sx={{ + order: { + xs: 1, + sm: 'unset' + } + }} > diff --git a/src/apps/experimental/components/library/QueueButton.tsx b/src/apps/experimental/components/library/QueueButton.tsx index 31abe4d7b2..305594dd14 100644 --- a/src/apps/experimental/components/library/QueueButton.tsx +++ b/src/apps/experimental/components/library/QueueButton.tsx @@ -34,6 +34,12 @@ const QueueButton: FC = ({ item, items, hasFilters }) => { title={globalize.translate('AddToPlayQueue')} className='paper-icon-button-light btnQueue autoSize' onClick={queue} + sx={{ + order: { + xs: 3, + sm: 'unset' + } + }} > diff --git a/src/apps/experimental/components/library/ShuffleButton.tsx b/src/apps/experimental/components/library/ShuffleButton.tsx index d20c401e5c..9c11ef00eb 100644 --- a/src/apps/experimental/components/library/ShuffleButton.tsx +++ b/src/apps/experimental/components/library/ShuffleButton.tsx @@ -42,6 +42,12 @@ const ShuffleButton: FC = ({ item, items, viewType, hasFilte title={globalize.translate('Shuffle')} className='paper-icon-button-light btnShuffle autoSize' onClick={shuffle} + sx={{ + order: { + xs: 2, + sm: 'unset' + } + }} > diff --git a/src/apps/experimental/components/tabs/AppTabs.tsx b/src/apps/experimental/components/tabs/AppTabs.tsx deleted file mode 100644 index d5f772d31d..0000000000 --- a/src/apps/experimental/components/tabs/AppTabs.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Theme } from '@mui/material/styles'; -import Tab from '@mui/material/Tab'; -import Tabs from '@mui/material/Tabs'; -import useMediaQuery from '@mui/material/useMediaQuery'; -import { debounce } from 'lodash-es'; -import React, { FC, useCallback, useEffect } from 'react'; -import { Route, Routes } from 'react-router-dom'; - -import TabRoutes from './tabRoutes'; -import useCurrentTab from 'hooks/useCurrentTab'; -import globalize from 'lib/globalize'; - -interface AppTabsParams { - isDrawerOpen: boolean -} - -const handleResize = debounce(() => window.dispatchEvent(new Event('resize')), 100); - -const AppTabs: FC = ({ - isDrawerOpen -}) => { - const isBigScreen = useMediaQuery((theme: Theme) => theme.breakpoints.up('sm')); - const { searchParams, setSearchParams, activeTab } = useCurrentTab(); - - // HACK: Force resizing to workaround upstream bug with tab resizing - // https://github.com/mui/material-ui/issues/24011 - useEffect(() => { - handleResize(); - }, [ isDrawerOpen ]); - - const onTabClick = useCallback((event: React.MouseEvent) => { - event.preventDefault(); - - const tabIndex = event.currentTarget.dataset.tabIndex; - - if (tabIndex) { - searchParams.set('tab', tabIndex); - setSearchParams(searchParams); - } - }, [ searchParams, setSearchParams ]); - - return ( - - { - TabRoutes.map(route => ( - - { - route.tabs.map(({ index, label }) => ( - - )) - } - - } - /> - )) - } - - ); -}; - -export default AppTabs; diff --git a/src/apps/experimental/constants/PseudoUserViews.ts b/src/apps/experimental/constants/PseudoUserViews.ts new file mode 100644 index 0000000000..ee1f4bebe8 --- /dev/null +++ b/src/apps/experimental/constants/PseudoUserViews.ts @@ -0,0 +1,11 @@ +import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto'; + +/** + * Views in the web app that we treat as UserViews. + */ +export const PseudoUserViews: Record = { + Favorites: { + Id: 'favorites', + Name: 'Favorites' + } +}; diff --git a/src/apps/experimental/routes/video/index.tsx b/src/apps/experimental/routes/video/index.tsx index b3ded898a8..f9322352d5 100644 --- a/src/apps/experimental/routes/video/index.tsx +++ b/src/apps/experimental/routes/video/index.tsx @@ -46,7 +46,6 @@ const VideoPage: FC = () => { diff --git a/src/components/toolbar/AppToolbar.tsx b/src/components/toolbar/AppToolbar.tsx index 4c34aaf3c1..8e46f07693 100644 --- a/src/components/toolbar/AppToolbar.tsx +++ b/src/components/toolbar/AppToolbar.tsx @@ -16,8 +16,8 @@ interface AppToolbarProps { buttons?: ReactNode isDrawerAvailable: boolean isDrawerOpen: boolean - onDrawerButtonClick?: (event: React.MouseEvent) => void, - isFullscreen?: boolean, + onDrawerButtonClick?: (event: React.MouseEvent) => void + isBackButtonAvailable?: boolean isUserMenuAvailable?: boolean } @@ -34,31 +34,21 @@ const AppToolbar: FC> = ({ isDrawerAvailable, isDrawerOpen, onDrawerButtonClick = () => { /* no-op */ }, - isFullscreen = false, + isBackButtonAvailable = false, isUserMenuAvailable = true }) => { const { user } = useApi(); const isUserLoggedIn = Boolean(user); - const isBackButtonAvailable = appRouter.canGoBack(); - - // Only use the left safe area padding when the drawer is not pinned or in a fullscreen view - const useSafeAreaLeft = isDrawerAvailable || isFullscreen; - return ( { + const { + data: systemInfo, + isPending + } = useSystemInfo(); + + return ( + + ); +}; + +export default ServerButton;