mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 06:18:45 +08:00
feat(component): init app sidebar (#2135)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { Tooltip } from '@affine/component';
|
||||
import { appSidebarOpenAtom } from '@affine/component/app-sidebar';
|
||||
import { getEnvironment } from '@affine/env';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
@@ -8,7 +10,6 @@ import {
|
||||
useGuideHiddenUntilNextUpdate,
|
||||
useUpdateTipsOnVersionChange,
|
||||
} from '../../../hooks/use-is-first-load';
|
||||
import { useSidebarStatus } from '../../../hooks/use-sidebar-status';
|
||||
import { SidebarSwitchIcon } from './icons';
|
||||
import { StyledSidebarSwitch } from './style';
|
||||
type SidebarSwitchProps = {
|
||||
@@ -24,7 +25,7 @@ export const SidebarSwitch = ({
|
||||
...props
|
||||
}: SidebarSwitchProps) => {
|
||||
useUpdateTipsOnVersionChange();
|
||||
const [open, setOpen] = useSidebarStatus();
|
||||
const [open, setOpen] = useAtom(appSidebarOpenAtom);
|
||||
const [tooltipVisible, setTooltipVisible] = useState(false);
|
||||
const [guideHidden, setGuideHidden] = useGuideHidden();
|
||||
const [guideHiddenUntilNextUpdate, setGuideHiddenUntilNextUpdate] =
|
||||
@@ -56,9 +57,9 @@ export const SidebarSwitch = ({
|
||||
visible={visible}
|
||||
disabled={!visible}
|
||||
onClick={useCallback(() => {
|
||||
setOpen(!open);
|
||||
setOpen(open => !open);
|
||||
setTooltipVisible(false);
|
||||
if (guideHiddenUntilNextUpdate['quickSearchTips'] === false) {
|
||||
if (!guideHiddenUntilNextUpdate['quickSearchTips']) {
|
||||
setGuideHiddenUntilNextUpdate({
|
||||
...guideHiddenUntilNextUpdate,
|
||||
quickSearchTips: true,
|
||||
@@ -70,7 +71,6 @@ export const SidebarSwitch = ({
|
||||
}, [
|
||||
guideHidden,
|
||||
guideHiddenUntilNextUpdate,
|
||||
open,
|
||||
setGuideHidden,
|
||||
setGuideHiddenUntilNextUpdate,
|
||||
setOpen,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { appSidebarOpenAtom } from '@affine/component/app-sidebar';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { CloseIcon } from '@blocksuite/icons';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { useAtom } from 'jotai';
|
||||
import type { FC, HTMLAttributes, PropsWithChildren } from 'react';
|
||||
import {
|
||||
forwardRef,
|
||||
@@ -12,10 +14,6 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import {
|
||||
useSidebarFloating,
|
||||
useSidebarStatus,
|
||||
} from '../../../hooks/use-sidebar-status';
|
||||
import type { AffineOfficialWorkspace } from '../../../shared';
|
||||
import { EditorOptionMenu } from './header-right-items/EditorOptionMenu';
|
||||
import EditPage from './header-right-items/EditPage';
|
||||
@@ -142,17 +140,11 @@ export const Header = forwardRef<
|
||||
useEffect(() => {
|
||||
setShowWarning(shouldShowWarning());
|
||||
}, []);
|
||||
const [open] = useSidebarStatus();
|
||||
const sidebarFloating = useSidebarFloating();
|
||||
const [open] = useAtom(appSidebarOpenAtom);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<StyledHeaderContainer
|
||||
sidebarFloating={sidebarFloating && open}
|
||||
ref={ref}
|
||||
hasWarning={showWarning}
|
||||
{...props}
|
||||
>
|
||||
<StyledHeaderContainer ref={ref} hasWarning={showWarning} {...props}>
|
||||
<BrowserWarning
|
||||
show={showWarning}
|
||||
onClose={() => {
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
|
||||
export const StyledHeaderContainer = styled('div')<{
|
||||
hasWarning: boolean;
|
||||
sidebarFloating: boolean;
|
||||
}>(({ theme, hasWarning, sidebarFloating }) => {
|
||||
}>(({ hasWarning }) => {
|
||||
return {
|
||||
height: hasWarning ? '96px' : '52px',
|
||||
flexShrink: 0,
|
||||
@@ -16,10 +15,6 @@ export const StyledHeaderContainer = styled('div')<{
|
||||
top: 0,
|
||||
background: 'var(--affine-background-primary-color)',
|
||||
zIndex: 1,
|
||||
WebkitAppRegion: sidebarFloating ? '' : 'drag',
|
||||
button: {
|
||||
WebkitAppRegion: 'no-drag',
|
||||
},
|
||||
};
|
||||
});
|
||||
export const StyledHeader = styled('div')<{ hasWarning: boolean }>(
|
||||
|
||||
@@ -1,47 +1,6 @@
|
||||
import { config } from '@affine/env';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import {
|
||||
DeleteTemporarilyIcon,
|
||||
FolderIcon,
|
||||
PlusIcon,
|
||||
SearchIcon,
|
||||
SettingsIcon,
|
||||
ShareIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import type { Page, PageMeta } from '@blocksuite/store';
|
||||
import type React from 'react';
|
||||
import type { UIEvent } from 'react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
useSidebarFloating,
|
||||
useSidebarResizing,
|
||||
useSidebarStatus,
|
||||
useSidebarWidth,
|
||||
} from '../../../hooks/use-sidebar-status';
|
||||
import type { AllWorkspace } from '../../../shared';
|
||||
import { ChangeLog } from './changeLog';
|
||||
import Favorite from './favorite';
|
||||
import { RouteNavigation } from './RouteNavigation';
|
||||
import { StyledListItem } from './shared-styles';
|
||||
import {
|
||||
StyledLink,
|
||||
StyledNewPageButton,
|
||||
StyledScrollWrapper,
|
||||
StyledSidebarHeader,
|
||||
StyledSliderBar,
|
||||
StyledSliderBarInnerWrapper,
|
||||
StyledSliderBarWrapper,
|
||||
StyledSliderModalBackground,
|
||||
} from './style';
|
||||
import { WorkspaceSelector } from './WorkspaceSelector';
|
||||
|
||||
const SidebarSwitch = lazy(() =>
|
||||
import('../../affine/sidebar-switch').then(module => ({
|
||||
default: module.SidebarSwitch,
|
||||
}))
|
||||
);
|
||||
|
||||
export type FavoriteListProps = {
|
||||
currentPageId: string | null;
|
||||
@@ -67,204 +26,3 @@ export type WorkSpaceSliderBarProps = {
|
||||
shared: (workspaceId: string) => string;
|
||||
};
|
||||
};
|
||||
|
||||
export const WorkSpaceSliderBar: React.FC<WorkSpaceSliderBarProps> = ({
|
||||
isPublicWorkspace,
|
||||
currentWorkspace,
|
||||
currentPageId,
|
||||
openPage,
|
||||
createPage,
|
||||
currentPath,
|
||||
paths,
|
||||
onOpenQuickSearchModal,
|
||||
onOpenWorkspaceListModal,
|
||||
}) => {
|
||||
const currentWorkspaceId = currentWorkspace?.id || null;
|
||||
const blockSuiteWorkspace = currentWorkspace?.blockSuiteWorkspace;
|
||||
const { t } = useTranslation();
|
||||
const [sidebarOpen, setSidebarOpen] = useSidebarStatus();
|
||||
const onClickNewPage = useCallback(async () => {
|
||||
const page = await createPage();
|
||||
openPage(page.id);
|
||||
}, [createPage, openPage]);
|
||||
const floatingSlider = useSidebarFloating();
|
||||
const [sliderWidth] = useSidebarWidth();
|
||||
const [isResizing] = useSidebarResizing();
|
||||
const [isScrollAtTop, setIsScrollAtTop] = useState(true);
|
||||
const show = isPublicWorkspace ? false : sidebarOpen;
|
||||
const actualWidth = floatingSlider ? 'calc(10vw + 400px)' : sliderWidth;
|
||||
|
||||
useEffect(() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.onSidebarVisibilityChange(sidebarOpen);
|
||||
}
|
||||
}, [sidebarOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
const keydown = (e: KeyboardEvent) => {
|
||||
if ((e.key === '/' && e.metaKey) || (e.key === '/' && e.ctrlKey)) {
|
||||
setSidebarOpen(!sidebarOpen);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', keydown, { capture: true });
|
||||
return () =>
|
||||
document.removeEventListener('keydown', keydown, { capture: true });
|
||||
}, [sidebarOpen, setSidebarOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledSliderBarWrapper
|
||||
resizing={isResizing}
|
||||
floating={floatingSlider}
|
||||
show={show}
|
||||
style={{ width: actualWidth }}
|
||||
data-testid="sliderBar-root"
|
||||
>
|
||||
<StyledSliderBar>
|
||||
<StyledSidebarHeader>
|
||||
<RouteNavigation />
|
||||
<Suspense>
|
||||
<SidebarSwitch
|
||||
visible={sidebarOpen}
|
||||
tooltipContent={t('Collapse sidebar')}
|
||||
data-testid="sliderBar-arrowButton-collapse"
|
||||
/>
|
||||
</Suspense>
|
||||
</StyledSidebarHeader>
|
||||
|
||||
<StyledSliderBarInnerWrapper data-testid="sliderBar-inner">
|
||||
<WorkspaceSelector
|
||||
currentWorkspace={currentWorkspace}
|
||||
onClick={onOpenWorkspaceListModal}
|
||||
/>
|
||||
<ChangeLog />
|
||||
<StyledListItem
|
||||
data-testid="slider-bar-quick-search-button"
|
||||
onClick={useCallback(() => {
|
||||
onOpenQuickSearchModal();
|
||||
}, [onOpenQuickSearchModal])}
|
||||
>
|
||||
<SearchIcon />
|
||||
{t('Quick search')}
|
||||
</StyledListItem>
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.setting(currentWorkspaceId))
|
||||
}
|
||||
data-testid="slider-bar-workspace-setting-button"
|
||||
style={{
|
||||
marginBottom: '16px',
|
||||
}}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.setting(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<SettingsIcon />
|
||||
<div>{t('Workspace Settings')}</div>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.all(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname: currentWorkspaceId && paths.all(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<FolderIcon />
|
||||
<span data-testid="all-pages">{t('All pages')}</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
<StyledScrollWrapper
|
||||
showTopBorder={!isScrollAtTop}
|
||||
onScroll={(e: UIEvent<HTMLDivElement>) => {
|
||||
(e.target as HTMLDivElement).scrollTop === 0
|
||||
? setIsScrollAtTop(true)
|
||||
: setIsScrollAtTop(false);
|
||||
}}
|
||||
>
|
||||
{blockSuiteWorkspace && (
|
||||
<Favorite
|
||||
currentPath={currentPath}
|
||||
paths={paths}
|
||||
currentPageId={currentPageId}
|
||||
openPage={openPage}
|
||||
currentWorkspace={currentWorkspace}
|
||||
/>
|
||||
)}
|
||||
</StyledScrollWrapper>
|
||||
<div style={{ height: 16 }}></div>
|
||||
{config.enableLegacyCloud &&
|
||||
(currentWorkspace?.flavour === WorkspaceFlavour.AFFINE &&
|
||||
currentWorkspace.public ? (
|
||||
<StyledListItem>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.setting(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span data-testid="Published-to-web">Published to web</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
) : (
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.shared(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.shared(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span data-testid="shared-pages">{t('Shared Pages')}</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
))}
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.trash(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.trash(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<DeleteTemporarilyIcon /> {t('Trash')}
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
</StyledSliderBarInnerWrapper>
|
||||
|
||||
<StyledNewPageButton
|
||||
data-testid="new-page-button"
|
||||
onClick={onClickNewPage}
|
||||
>
|
||||
<PlusIcon /> {t('New Page')}
|
||||
</StyledNewPageButton>
|
||||
</StyledSliderBar>
|
||||
</StyledSliderBarWrapper>
|
||||
<StyledSliderModalBackground
|
||||
data-testid="sliderBar-modalBackground"
|
||||
active={floatingSlider && sidebarOpen}
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkSpaceSliderBar;
|
||||
|
||||
@@ -2,60 +2,10 @@ import { displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
import Link from 'next/link';
|
||||
|
||||
const macosElectron = environment.isDesktop && environment.isMacOs;
|
||||
|
||||
export const StyledSliderBarWrapper = styled('div')<{
|
||||
show: boolean;
|
||||
floating: boolean;
|
||||
resizing: boolean;
|
||||
}>(({ theme, show, floating, resizing }) => {
|
||||
return {
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
'button, a': {
|
||||
userSelect: 'none',
|
||||
},
|
||||
zIndex: 'var(--affine-z-index-modal)',
|
||||
transition: resizing ? '' : 'transform .3s, width .3s, max-width .3s',
|
||||
transform: show ? 'translateX(0)' : 'translateX(-100%)',
|
||||
maxWidth: floating ? 'calc(10vw + 400px)' : 'calc(100vw - 698px)',
|
||||
background:
|
||||
!floating && macosElectron
|
||||
? 'transparent'
|
||||
: 'var(--affine-background-secondary-color)',
|
||||
borderRight: macosElectron ? '' : '1px solid',
|
||||
borderColor: 'var(--affine-border-color)',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledSliderBar = styled('div')(() => {
|
||||
return {
|
||||
whiteSpace: 'nowrap',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
padding: '0 4px',
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
};
|
||||
});
|
||||
export const StyledSidebarHeader = styled('div')(() => {
|
||||
return {
|
||||
height: '52px',
|
||||
flexShrink: 0,
|
||||
padding: '0 16px 0 10px',
|
||||
WebkitAppRegion: 'drag',
|
||||
button: {
|
||||
WebkitAppRegion: 'no-drag',
|
||||
},
|
||||
...displayFlex(macosElectron ? 'flex-end' : 'space-between', 'center'),
|
||||
};
|
||||
});
|
||||
export const StyledSliderBarInnerWrapper = styled('div')(() => {
|
||||
return {
|
||||
flexGrow: 1,
|
||||
// overflowX: 'hidden',
|
||||
// overflowY: 'auto',
|
||||
margin: '0 2px',
|
||||
position: 'relative',
|
||||
height: 'calc(100% - 52px * 2)',
|
||||
display: 'flex',
|
||||
@@ -91,8 +41,6 @@ export const StyledNewPageButton = styled('button')(({ theme }) => {
|
||||
return {
|
||||
height: '52px',
|
||||
...displayFlex('flex-start', 'center'),
|
||||
borderTop: '1px solid',
|
||||
borderColor: 'var(--affine-border-color)',
|
||||
padding: '0 8px 0 16px',
|
||||
svg: {
|
||||
fontSize: '20px',
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
import {
|
||||
AppSidebar,
|
||||
appSidebarOpenAtom,
|
||||
ResizeIndicator,
|
||||
} from '@affine/component/app-sidebar';
|
||||
import { config } from '@affine/env';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import {
|
||||
DeleteTemporarilyIcon,
|
||||
FolderIcon,
|
||||
PlusIcon,
|
||||
SearchIcon,
|
||||
SettingsIcon,
|
||||
ShareIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import type { ReactElement, UIEvent } from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import type { AllWorkspace } from '../../shared';
|
||||
import ChangeLog from '../pure/workspace-slider-bar/changeLog';
|
||||
import Favorite from '../pure/workspace-slider-bar/favorite';
|
||||
import { StyledListItem } from '../pure/workspace-slider-bar/shared-styles';
|
||||
import {
|
||||
StyledLink,
|
||||
StyledNewPageButton,
|
||||
StyledScrollWrapper,
|
||||
StyledSliderBarInnerWrapper,
|
||||
} from '../pure/workspace-slider-bar/style';
|
||||
import { WorkspaceSelector } from '../pure/workspace-slider-bar/WorkspaceSelector';
|
||||
|
||||
export type RootAppSidebarProps = {
|
||||
isPublicWorkspace: boolean;
|
||||
onOpenQuickSearchModal: () => void;
|
||||
onOpenWorkspaceListModal: () => void;
|
||||
currentWorkspace: AllWorkspace | null;
|
||||
currentPageId: string | null;
|
||||
openPage: (pageId: string) => void;
|
||||
createPage: () => Page;
|
||||
currentPath: string;
|
||||
paths: {
|
||||
all: (workspaceId: string) => string;
|
||||
favorite: (workspaceId: string) => string;
|
||||
trash: (workspaceId: string) => string;
|
||||
setting: (workspaceId: string) => string;
|
||||
shared: (workspaceId: string) => string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This is for the whole affine app sidebar.
|
||||
* This component wraps the app sidebar in `@affine/component` with logic and data.
|
||||
*
|
||||
* @todo(himself65): rewrite all styled component into @vanilla-extract/css
|
||||
*/
|
||||
export const RootAppSidebar = ({
|
||||
currentWorkspace,
|
||||
currentPageId,
|
||||
openPage,
|
||||
createPage,
|
||||
currentPath,
|
||||
paths,
|
||||
onOpenQuickSearchModal,
|
||||
onOpenWorkspaceListModal,
|
||||
}: RootAppSidebarProps): ReactElement => {
|
||||
const currentWorkspaceId = currentWorkspace?.id || null;
|
||||
const blockSuiteWorkspace = currentWorkspace?.blockSuiteWorkspace;
|
||||
const { t } = useTranslation();
|
||||
const [isScrollAtTop, setIsScrollAtTop] = useState(true);
|
||||
const onClickNewPage = useCallback(async () => {
|
||||
const page = await createPage();
|
||||
openPage(page.id);
|
||||
}, [createPage, openPage]);
|
||||
const sidebarOpen = useAtomValue(appSidebarOpenAtom);
|
||||
useEffect(() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.onSidebarVisibilityChange(sidebarOpen);
|
||||
}
|
||||
}, [sidebarOpen]);
|
||||
const ref = useRef<HTMLElement>(null);
|
||||
return (
|
||||
<>
|
||||
<AppSidebar
|
||||
ref={ref}
|
||||
footer={
|
||||
<StyledNewPageButton
|
||||
data-testid="new-page-button"
|
||||
onClick={onClickNewPage}
|
||||
>
|
||||
<PlusIcon /> {t('New Page')}
|
||||
</StyledNewPageButton>
|
||||
}
|
||||
>
|
||||
<StyledSliderBarInnerWrapper data-testid="sliderBar-inner">
|
||||
<WorkspaceSelector
|
||||
currentWorkspace={currentWorkspace}
|
||||
onClick={onOpenWorkspaceListModal}
|
||||
/>
|
||||
<ChangeLog />
|
||||
<StyledListItem
|
||||
data-testid="slider-bar-quick-search-button"
|
||||
onClick={useCallback(() => {
|
||||
onOpenQuickSearchModal();
|
||||
}, [onOpenQuickSearchModal])}
|
||||
>
|
||||
<SearchIcon />
|
||||
{t('Quick search')}
|
||||
</StyledListItem>
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.setting(currentWorkspaceId))
|
||||
}
|
||||
data-testid="slider-bar-workspace-setting-button"
|
||||
style={{
|
||||
marginBottom: '16px',
|
||||
}}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.setting(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<SettingsIcon />
|
||||
<div>{t('Workspace Settings')}</div>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.all(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname: currentWorkspaceId && paths.all(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<FolderIcon />
|
||||
<span data-testid="all-pages">{t('All pages')}</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
<StyledScrollWrapper
|
||||
showTopBorder={!isScrollAtTop}
|
||||
onScroll={(e: UIEvent<HTMLDivElement>) => {
|
||||
(e.target as HTMLDivElement).scrollTop === 0
|
||||
? setIsScrollAtTop(true)
|
||||
: setIsScrollAtTop(false);
|
||||
}}
|
||||
>
|
||||
{blockSuiteWorkspace && (
|
||||
<Favorite
|
||||
currentPath={currentPath}
|
||||
paths={paths}
|
||||
currentPageId={currentPageId}
|
||||
openPage={openPage}
|
||||
currentWorkspace={currentWorkspace}
|
||||
/>
|
||||
)}
|
||||
</StyledScrollWrapper>
|
||||
<div style={{ height: 16 }}></div>
|
||||
{config.enableLegacyCloud &&
|
||||
(currentWorkspace?.flavour === WorkspaceFlavour.AFFINE &&
|
||||
currentWorkspace.public ? (
|
||||
<StyledListItem>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.setting(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span data-testid="Published-to-web">Published to web</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
) : (
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.shared(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname:
|
||||
currentWorkspaceId && paths.shared(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<ShareIcon />
|
||||
<span data-testid="shared-pages">{t('Shared Pages')}</span>
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
))}
|
||||
<StyledListItem
|
||||
active={
|
||||
currentPath ===
|
||||
(currentWorkspaceId && paths.trash(currentWorkspaceId))
|
||||
}
|
||||
>
|
||||
<StyledLink
|
||||
href={{
|
||||
pathname: currentWorkspaceId && paths.trash(currentWorkspaceId),
|
||||
}}
|
||||
>
|
||||
<DeleteTemporarilyIcon /> {t('Trash')}
|
||||
</StyledLink>
|
||||
</StyledListItem>
|
||||
</StyledSliderBarInnerWrapper>
|
||||
</AppSidebar>
|
||||
<ResizeIndicator targetElement={ref} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user