diff --git a/apps/web/app/root.tsx b/apps/web/app/root.tsx index 003337d4c6..0742adc55e 100644 --- a/apps/web/app/root.tsx +++ b/apps/web/app/root.tsx @@ -15,7 +15,6 @@ import icon180 from "@/app/assets/icons/icon-180x180.png?url"; import icon512 from "@/app/assets/icons/icon-512x512.png?url"; import ogImage from "@/app/assets/og-image.png?url"; import { LogoSpinner } from "@/components/common/logo-spinner"; -import { DesktopAppProviderRoot } from "@/plane-web/components/desktop/root"; import { TrialBanner } from "@/plane-web/components/license/banner/trial-banner"; import globalStyles from "@/styles/globals.css?url"; import type { Route } from "./+types/root"; @@ -60,11 +59,10 @@ export function Layout({ children }: { children: ReactNode }) {
-
{/* free trial banner */} diff --git a/apps/web/ee/components/common/extended-app-header.tsx b/apps/web/ee/components/common/extended-app-header.tsx index 93f662c311..d0fb4e798b 100644 --- a/apps/web/ee/components/common/extended-app-header.tsx +++ b/apps/web/ee/components/common/extended-app-header.tsx @@ -6,8 +6,6 @@ import { AppSidebarToggleButton } from "@/components/sidebar/sidebar-toggle-butt // hooks import { useAppTheme } from "@/hooks/store/use-app-theme"; import { useProjectNavigationPreferences } from "@/hooks/use-navigation-preferences"; -// local imports -import { isSidebarToggleVisible } from "../desktop/helper"; export const ExtendedAppHeader = observer((props: { header: ReactNode }) => { const { header } = props; @@ -22,7 +20,7 @@ export const ExtendedAppHeader = observer((props: { header: ReactNode }) => { return ( <> - {isSidebarToggleVisible() && sidebarCollapsed && shouldShowSidebarToggleButton && } + {sidebarCollapsed && shouldShowSidebarToggleButton && }
{header}
diff --git a/apps/web/ee/components/desktop/context/index.tsx b/apps/web/ee/components/desktop/context/index.tsx index f831d8669e..7655603aab 100644 --- a/apps/web/ee/components/desktop/context/index.tsx +++ b/apps/web/ee/components/desktop/context/index.tsx @@ -2,12 +2,12 @@ import { createContext, useEffect, useState, useMemo, useCallback } from "react"; // todesktop -import { nativeWindow, webContents } from "@todesktop/client-core"; +import { nativeWindow } from "@todesktop/client-core"; +import { isDesktopApp } from "@todesktop/client-core/platform/todesktop"; // mobx import { observer } from "mobx-react"; export type TDesktopAppContext = { - pageTitle: string; isFullScreen: boolean; }; @@ -20,9 +20,8 @@ export type TDesktopAppProviderProps = { export const DesktopAppProvider = observer((props: TDesktopAppProviderProps) => { const { children } = props; // states - const [pageTitle, setPageTitle] = useState(document.title); const [isFullScreen, setIsFullScreen] = useState(false); - + // derived // handle theme change const handleThemeChange = useCallback(() => { const currentTheme = localStorage.getItem("theme") || "light"; @@ -30,16 +29,11 @@ export const DesktopAppProvider = observer((props: TDesktopAppProviderProps) => }, []); useEffect(() => { + if (!isDesktopApp()) return; + const cleanupFunctions: (() => Promise | void)[] = []; // Setup observers - const setupTitleChangeObserver = async () => { - const unsubscribe = await webContents.on("page-title-updated", () => { - setPageTitle(document.title); - }); - cleanupFunctions.push(unsubscribe); - }; - const setupFullScreenObservers = async () => { setIsFullScreen(await nativeWindow.isFullscreen()); @@ -60,7 +54,6 @@ export const DesktopAppProvider = observer((props: TDesktopAppProviderProps) => // Call observers handleThemeChange(); - setupTitleChangeObserver(); setupFullScreenObservers(); setupThemeObserver(); @@ -70,7 +63,7 @@ export const DesktopAppProvider = observer((props: TDesktopAppProviderProps) => }; }, [handleThemeChange]); - const contextValue = useMemo(() => ({ pageTitle, isFullScreen }), [pageTitle, isFullScreen]); + const contextValue = useMemo(() => ({ isFullScreen }), [isFullScreen]); return {children}; }); diff --git a/apps/web/ee/components/desktop/index.ts b/apps/web/ee/components/desktop/index.ts index 30d634c2bb..2e18ec62a6 100644 --- a/apps/web/ee/components/desktop/index.ts +++ b/apps/web/ee/components/desktop/index.ts @@ -4,3 +4,5 @@ export * from "./sidebar-toggle"; export * from "./navigation"; export * from "./use-desktop-app"; export * from "./helper"; +export * from "./sidebar-workspace-menu"; + diff --git a/apps/web/ee/components/desktop/navigation.tsx b/apps/web/ee/components/desktop/navigation.tsx index 97b2bdb81a..d4fa7010a3 100644 --- a/apps/web/ee/components/desktop/navigation.tsx +++ b/apps/web/ee/components/desktop/navigation.tsx @@ -36,7 +36,8 @@ export const DesktopAppNavigation = observer(() => { observerNavigationEvents(); return () => { - unsubscribeNavigationEvent && unsubscribeNavigationEvent(); + if (!unsubscribeNavigationEvent) return; + unsubscribeNavigationEvent(); }; }, []); diff --git a/apps/web/ee/components/desktop/root.tsx b/apps/web/ee/components/desktop/root.tsx index 14f41d5dbe..4ed77ddbec 100644 --- a/apps/web/ee/components/desktop/root.tsx +++ b/apps/web/ee/components/desktop/root.tsx @@ -1,49 +1,42 @@ "use client"; -import type { FC } from "react"; -// to desktop -import { isDesktopApp } from "@todesktop/client-core/platform/todesktop"; -// mobx +import { useMemo } from "react"; +import { isDesktopApp as isDesktopAppFn } from "@todesktop/client-core/platform/todesktop"; import { observer } from "mobx-react"; // helpers import { cn } from "@plane/utils"; // desktop app components -import { SidebarToggle, DesktopAppNavigation, useDesktopApp, DesktopAppProvider } from "@/plane-web/components/desktop"; +import { + DesktopSidebarToggle, + DesktopAppNavigation, + useDesktopApp, + DesktopAppProvider, +} from "@/plane-web/components/desktop"; -const DesktopAppRoot: FC = observer(() => { +const DesktopHeaderRoot = observer(function DesktopHeaderRoot() { // store hooks - const { pageTitle, isFullScreen } = useDesktopApp(); + const { isFullScreen } = useDesktopApp(); + // derived values + const isDesktopApp = useMemo(() => isDesktopAppFn(), []); + if (!isDesktopApp) return null; return ( - <> -
-
- - -
-
- {/* page title */} -
{pageTitle}
-
-
-
- +
+ + +
); }); -export const DesktopAppProviderRoot: FC = observer(() => { - if (!isDesktopApp()) return null; - +export const DesktopHeaderProvider = observer(function DesktopHeaderProvider() { return ( - + ); }); diff --git a/apps/web/ee/components/desktop/sidebar-toggle.tsx b/apps/web/ee/components/desktop/sidebar-toggle.tsx index c53eafd0a6..1f5e4966a2 100644 --- a/apps/web/ee/components/desktop/sidebar-toggle.tsx +++ b/apps/web/ee/components/desktop/sidebar-toggle.tsx @@ -11,20 +11,20 @@ import { cn } from "@plane/utils"; // hooks import { useAppTheme } from "@/hooks/store/use-app-theme"; -export const SidebarToggle = observer(() => { +export const DesktopSidebarToggle = observer(function DesktopSidebarToggle() { // router const { workspaceSlug } = useParams(); const pathname = usePathname(); // store hooks const { sidebarCollapsed, toggleSidebar } = useAppTheme(); // derived values - const isSidebarAccessible = !!workspaceSlug?.toString() || pathname.includes("/profile/"); + const isSettingsPath = workspaceSlug && pathname.includes(`/${workspaceSlug}/settings`); + const isNotificationsPath = workspaceSlug && pathname.includes(`/${workspaceSlug}/notifications`); + const sidebarInaccessiblePaths = isSettingsPath || isNotificationsPath; + const isSidebarAccessible = workspaceSlug && !sidebarInaccessiblePaths; const isSidebarCollapsed = useMemo(() => sidebarCollapsed, [sidebarCollapsed]); - if (!isSidebarAccessible) { - return null; - } - + if (!isSidebarAccessible) return null; return ( <> diff --git a/apps/web/ee/components/desktop/sidebar-workspace-menu.tsx b/apps/web/ee/components/desktop/sidebar-workspace-menu.tsx new file mode 100644 index 0000000000..4f84cebd97 --- /dev/null +++ b/apps/web/ee/components/desktop/sidebar-workspace-menu.tsx @@ -0,0 +1,12 @@ +import { isDesktopApp } from "@todesktop/client-core/platform/todesktop"; +// components +import { WorkspaceMenuRoot } from "@/components/workspace/sidebar/workspace-menu-root"; + +export function DesktopSidebarWorkspaceMenu() { + if (!isDesktopApp()) return null; + return ( +
+ +
+ ); +} diff --git a/apps/web/ee/components/desktop/use-desktop-app.ts b/apps/web/ee/components/desktop/use-desktop-app.ts index 8d903de03e..2a2b3ab234 100644 --- a/apps/web/ee/components/desktop/use-desktop-app.ts +++ b/apps/web/ee/components/desktop/use-desktop-app.ts @@ -1,13 +1,10 @@ import { useContext } from "react"; -// todesktop -import { isDesktopApp } from "@todesktop/client-core/platform/todesktop"; // context import type { TDesktopAppContext } from "./context"; import { DesktopAppContext } from "./context"; export const useDesktopApp = (): TDesktopAppContext => { - if (!isDesktopApp()) throw new Error("useDesktopApp must be used in desktop app"); const context = useContext(DesktopAppContext); - if (context === undefined) throw new Error("useDesktopApp must be used within IssueModalProvider"); + if (context === undefined) throw new Error("useDesktopApp must be used within DesktopAppProvider"); return context; }; diff --git a/apps/web/ee/components/navigations/top-navigation-root.tsx b/apps/web/ee/components/navigations/top-navigation-root.tsx index 2d36d76664..736de7c21e 100644 --- a/apps/web/ee/components/navigations/top-navigation-root.tsx +++ b/apps/web/ee/components/navigations/top-navigation-root.tsx @@ -1,3 +1,5 @@ +import { useMemo } from "react"; +import { isDesktopApp as isDesktopAppFn } from "@todesktop/client-core/platform/todesktop"; import { observer } from "mobx-react"; import { useParams, usePathname } from "next/navigation"; import useSWR from "swr"; @@ -20,6 +22,7 @@ import { useAppRailPreferences } from "@/hooks/use-navigation-preferences"; import { useFlag, useWorkspaceFeatures } from "@/plane-web/hooks/store"; import { usePiChat } from "@/plane-web/hooks/store/use-pi-chat"; import { EWorkspaceFeatures } from "@/plane-web/types/workspace-feature"; +import { DesktopHeaderProvider } from "../desktop/root"; import { TopNavSearch } from "./top-nav-search"; export const TopNavigationRoot = observer(() => { @@ -29,10 +32,11 @@ export const TopNavigationRoot = observer(() => { const { isWorkspaceFeatureEnabled } = useWorkspaceFeatures(); const { unreadNotificationsCount, getUnreadNotificationsCount } = useWorkspaceNotifications(); const { preferences } = useAppRailPreferences(); - // router const { workspaceSlug, projectId, workItem } = useParams(); const pathname = usePathname(); + // derived + const isDesktopApp = useMemo(() => isDesktopAppFn(), []); // Fetch notification count useSWR( @@ -58,18 +62,21 @@ export const TopNavigationRoot = observer(() => { return (
{/* Workspace Menu */}
- + {!isDesktopApp && } + {isDesktopApp && }
{/* Power K Search */} -
{isAdvancedSearchEnabled && isOpenSearch ? : }
+
+ {isAdvancedSearchEnabled && isOpenSearch ? : } +
{/* Additional Actions */} -
+