136 lines
4.8 KiB
TypeScript
136 lines
4.8 KiB
TypeScript
|
|
import React, { useEffect, useRef, useState } from "react";
|
||
|
|
import { useLocation } from "react-router-dom";
|
||
|
|
import { ThemeProvider } from "styled-components";
|
||
|
|
import type { ApplicationPayload } from "@appsmith/constants/ReduxActionConstants";
|
||
|
|
import { useDispatch, useSelector } from "react-redux";
|
||
|
|
import type { AppState } from "@appsmith/reducers";
|
||
|
|
import {
|
||
|
|
getCurrentPageId,
|
||
|
|
getViewModePageList,
|
||
|
|
} from "selectors/editorSelectors";
|
||
|
|
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
|
||
|
|
import { getCurrentUser } from "selectors/usersSelectors";
|
||
|
|
import type { User } from "constants/userConstants";
|
||
|
|
import type { Theme } from "constants/DefaultTheme";
|
||
|
|
import { getThemeDetails, ThemeMode } from "selectors/themeSelectors";
|
||
|
|
import HtmlTitle from "../AppViewerHtmlTitle";
|
||
|
|
import { NAVIGATION_SETTINGS } from "constants/AppConstants";
|
||
|
|
import PageMenu from "pages/AppViewer/PageMenu";
|
||
|
|
import TourCompletionMessage from "pages/Editor/GuidedTour/TourCompletionMessage";
|
||
|
|
import { useHref } from "pages/Editor/utils";
|
||
|
|
import { builderURL } from "RouteBuilder";
|
||
|
|
import TopHeader from "./components/TopHeader";
|
||
|
|
import Sidebar from "./Sidebar";
|
||
|
|
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||
|
|
import { useIsMobileDevice } from "utils/hooks/useDeviceDetect";
|
||
|
|
import { setAppViewHeaderHeight } from "actions/appViewActions";
|
||
|
|
|
||
|
|
export function Navigation() {
|
||
|
|
const { search } = useLocation();
|
||
|
|
const queryParams = new URLSearchParams(search);
|
||
|
|
const isEmbed = queryParams.get("embed");
|
||
|
|
const hideHeader = !!isEmbed;
|
||
|
|
const [isMenuOpen, setMenuOpen] = useState(false);
|
||
|
|
const headerRef = useRef<HTMLDivElement>(null);
|
||
|
|
const pageId = useSelector(getCurrentPageId);
|
||
|
|
const editorURL = useHref(builderURL, { pageId });
|
||
|
|
const currentWorkspaceId: string = useSelector(getCurrentWorkspaceId);
|
||
|
|
const currentUser: User | undefined = useSelector(getCurrentUser);
|
||
|
|
const lightTheme: Theme = useSelector((state: AppState) =>
|
||
|
|
getThemeDetails(state, ThemeMode.LIGHT),
|
||
|
|
);
|
||
|
|
const currentApplicationDetails: ApplicationPayload | undefined = useSelector(
|
||
|
|
getCurrentApplication,
|
||
|
|
);
|
||
|
|
const pages = useSelector(getViewModePageList);
|
||
|
|
const isMobile = useIsMobileDevice();
|
||
|
|
const dispatch = useDispatch();
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const header = document.querySelector(".js-appviewer-header");
|
||
|
|
|
||
|
|
dispatch(setAppViewHeaderHeight(header?.clientHeight || 0));
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
dispatch(setAppViewHeaderHeight(0));
|
||
|
|
};
|
||
|
|
}, [
|
||
|
|
currentApplicationDetails?.applicationDetail?.navigationSetting?.navStyle,
|
||
|
|
currentApplicationDetails?.applicationDetail?.navigationSetting
|
||
|
|
?.orientation,
|
||
|
|
]);
|
||
|
|
|
||
|
|
const renderNavigation = () => {
|
||
|
|
if (
|
||
|
|
currentApplicationDetails?.applicationDetail?.navigationSetting
|
||
|
|
?.orientation === NAVIGATION_SETTINGS.ORIENTATION.SIDE
|
||
|
|
) {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
{/*
|
||
|
|
* We need to add top header since we want the current mobile
|
||
|
|
* navigation experience until we create the new sidebar for mobile.
|
||
|
|
*/}
|
||
|
|
{isMobile ? (
|
||
|
|
<TopHeader
|
||
|
|
currentApplicationDetails={currentApplicationDetails}
|
||
|
|
currentUser={currentUser}
|
||
|
|
currentWorkspaceId={currentWorkspaceId}
|
||
|
|
isMenuOpen={isMenuOpen}
|
||
|
|
pages={pages}
|
||
|
|
setMenuOpen={setMenuOpen}
|
||
|
|
/>
|
||
|
|
) : (
|
||
|
|
<Sidebar
|
||
|
|
currentApplicationDetails={currentApplicationDetails}
|
||
|
|
currentUser={currentUser}
|
||
|
|
currentWorkspaceId={currentWorkspaceId}
|
||
|
|
pages={pages}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<TopHeader
|
||
|
|
currentApplicationDetails={currentApplicationDetails}
|
||
|
|
currentUser={currentUser}
|
||
|
|
currentWorkspaceId={currentWorkspaceId}
|
||
|
|
isMenuOpen={isMenuOpen}
|
||
|
|
pages={pages}
|
||
|
|
setMenuOpen={setMenuOpen}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
if (hideHeader) return <HtmlTitle />;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<ThemeProvider theme={lightTheme}>
|
||
|
|
<div ref={headerRef}>
|
||
|
|
{/* Since the Backend doesn't have navigationSetting field by default
|
||
|
|
and we are creating the default values only when any nav settings via the
|
||
|
|
settings pane has changed, we need to hide the navbar ONLY when the showNavbar
|
||
|
|
setting is explicitly set to false by the user via the settings pane. */}
|
||
|
|
{currentApplicationDetails?.applicationDetail?.navigationSetting
|
||
|
|
?.showNavbar !== false && renderNavigation()}
|
||
|
|
|
||
|
|
{/* Mobile Sidebar */}
|
||
|
|
<PageMenu
|
||
|
|
application={currentApplicationDetails}
|
||
|
|
headerRef={headerRef}
|
||
|
|
isOpen={isMenuOpen}
|
||
|
|
pages={pages}
|
||
|
|
setMenuOpen={setMenuOpen}
|
||
|
|
url={editorURL}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<TourCompletionMessage />
|
||
|
|
</div>
|
||
|
|
</ThemeProvider>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export default Navigation;
|