feat!: affine cloud support (#3813)

Co-authored-by: Hongtao Lye <codert.sn@gmail.com>
Co-authored-by: liuyi <forehalo@gmail.com>
Co-authored-by: LongYinan <lynweklm@gmail.com>
Co-authored-by: X1a0t <405028157@qq.com>
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
Co-authored-by: xiaodong zuo <53252747+zuoxiaodong0815@users.noreply.github.com>
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
Co-authored-by: danielchim <kahungchim@gmail.com>
This commit is contained in:
Alex Yang
2023-08-29 05:07:05 -05:00
committed by GitHub
parent d0145c6f38
commit 2f6c4e3696
414 changed files with 19469 additions and 7591 deletions
@@ -1,13 +1,9 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Button } from '@toeverything/components/button';
import { CloseIcon } from '@blocksuite/icons';
import { Button, IconButton } from '@toeverything/components/button';
import { Modal, ModalCloseButton } from '../../..';
import {
StyledButtonContent,
StyledModalHeader,
StyledModalWrapper,
StyledTextContent,
} from './style';
import { Modal, ModalWrapper } from '../../..';
import { ButtonContainer, Content, Header, StyleTips, Title } from './style';
export type PublicLinkDisableProps = {
open: boolean;
@@ -23,29 +19,37 @@ export const PublicLinkDisableModal = ({
const t = useAFFiNEI18N();
return (
<Modal open={open} onClose={onClose}>
<StyledModalWrapper>
<ModalCloseButton onClick={onClose} top={12} right={12} />
<StyledModalHeader>{t['Disable Public Link ?']()}</StyledModalHeader>
<StyledTextContent>
{t['Disable Public Link Description']()}
</StyledTextContent>
<StyledButtonContent>
<Button onClick={onClose}>{t['Cancel']()}</Button>
<Button
type="error"
data-testid="disable-public-link-confirm-button"
onClick={() => {
onConfirmDisable();
onClose();
}}
style={{ marginLeft: '24px' }}
>
{t['Disable']()}
</Button>
</StyledButtonContent>
</StyledModalWrapper>
<ModalWrapper width={480}>
<Header>
<Title>{t['Disable Public Link']()}</Title>
<IconButton onClick={onClose}>
<CloseIcon />
</IconButton>
</Header>
<Content>
<StyleTips>{t['Disable Public Link Description']()}</StyleTips>
<ButtonContainer>
<div>
<Button onClick={onClose} block>
{t['Cancel']()}
</Button>
</div>
<div>
<Button
data-testid="confirm-enable-affine-cloud-button"
type="error"
block
onClick={() => {
onConfirmDisable();
onClose();
}}
>
{t['Disable']()}
</Button>
</div>
</ButtonContainer>
</Content>
</ModalWrapper>
</Modal>
);
};
@@ -1,42 +1,35 @@
import { styled } from '../../..';
export const StyledModalWrapper = styled('div')(() => {
return {
position: 'relative',
padding: '0px',
width: '560px',
background: 'var(--affine-white)',
borderRadius: '12px',
// height: '312px',
};
export const Header = styled('div')({
display: 'flex',
justifyContent: 'space-between',
paddingRight: '20px',
paddingTop: '20px',
paddingLeft: '24px',
alignItems: 'center',
});
export const StyledModalHeader = styled('div')(() => {
return {
margin: '44px 0px 12px 0px',
width: '560px',
fontWeight: '600',
fontSize: 'var(--affine-font-h6)',
textAlign: 'center',
};
export const Content = styled('div')({
padding: '12px 24px 20px 24px',
});
export const StyledTextContent = styled('div')(() => {
return {
margin: 'auto',
width: '560px',
padding: '0px 84px',
fontWeight: '400',
fontSize: 'var(--affine-font-base)',
textAlign: 'center',
};
export const Title = styled('div')({
fontSize: 'var(--affine-font-h6)',
lineHeight: '26px',
fontWeight: 600,
});
export const StyledButtonContent = styled('div')(() => {
export const StyleTips = styled('div')(() => {
return {
userSelect: 'none',
marginBottom: '20px',
};
});
export const ButtonContainer = styled('div')(() => {
return {
margin: '32px 0',
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
justifyContent: 'flex-end',
gap: '20px',
paddingTop: '20px',
};
});
@@ -1,27 +0,0 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
ExportToHtmlMenuItem,
ExportToMarkdownMenuItem,
ExportToPdfMenuItem,
ExportToPngMenuItem,
} from '../page-list/operation-menu-items/export';
import { actionsStyle, descriptionStyle, menuItemStyle } from './index.css';
// import type { ShareMenuProps } from './share-menu';
export const Export = () => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
<div className={descriptionStyle}>
{t['Export Shared Pages Description']()}
</div>
<div className={actionsStyle}>
<ExportToPdfMenuItem />
<ExportToHtmlMenuItem />
<ExportToPngMenuItem />
<ExportToMarkdownMenuItem />
</div>
</div>
);
};
@@ -1,16 +1,5 @@
import { style } from '@vanilla-extract/css';
export const tabStyle = style({
display: 'flex',
flex: '1',
width: '100%',
padding: '0 10px',
margin: '0',
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
});
export const menuItemStyle = style({
padding: '4px 18px',
paddingBottom: '16px',
@@ -20,9 +9,9 @@ export const menuItemStyle = style({
export const descriptionStyle = style({
wordWrap: 'break-word',
// wordBreak: 'break-all',
fontSize: '16px',
marginTop: '16px',
marginBottom: '16px',
fontSize: 'var(--affine-font-xs)',
lineHeight: '20px',
color: 'var(--affine-text-secondary-color)',
});
export const buttonStyle = style({
@@ -42,13 +31,103 @@ export const containerStyle = style({
display: 'flex',
width: '100%',
flexDirection: 'column',
gap: '8px',
});
export const indicatorContainerStyle = style({
position: 'relative',
});
export const inputButtonRowStyle = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
marginTop: '16px',
});
export const titleContainerStyle = style({
display: 'flex',
alignItems: 'center',
gap: '4px',
fontSize: 'var(--affine-font-sm)',
fontWeight: 600,
lineHeight: '22px',
padding: '0 4px',
});
export const subTitleStyle = style({
fontSize: 'var(--affine-font-sm)',
fontWeight: 500,
lineHeight: '22px',
});
export const columnContainerStyle = style({
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
padding: '0 4px',
width: '100%',
gap: '12px',
});
export const rowContainerStyle = style({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
gap: '12px',
padding: '4px',
});
export const radioButtonGroup = style({
display: 'flex',
justifyContent: 'flex-end',
padding: '2px',
minWidth: '154px',
maxWidth: '250px',
});
export const radioButton = style({
color: 'var(--affine-text-secondary-color)',
selectors: {
'&[data-state="checked"]': {
color: 'var(--affine-text-primary-color)',
},
},
});
export const spanStyle = style({
padding: '4px 20px',
});
export const disableSharePage = style({
color: 'var(--affine-error-color)',
});
export const localSharePage = style({
padding: '12px 8px',
display: 'flex',
alignItems: 'center',
borderRadius: '8px',
backgroundColor: 'var(--affine-background-secondary-color)',
minHeight: '108px',
position: 'relative',
});
export const cloudSvgContainer = style({
width: '100%',
height: '100%',
minWidth: '185px',
});
export const cloudSvgStyle = style({
width: '193px',
height: '108px',
position: 'absolute',
bottom: '0',
right: '8px',
});
export const shareIconStyle = style({
fontSize: '16px',
color: 'var(--affine-icon-color)',
display: 'flex',
alignItems: 'center',
});
@@ -0,0 +1,3 @@
import { atom } from 'jotai/vanilla';
export const enableShareMenuAtom = atom(false);
@@ -1,4 +1,3 @@
export * from './disable-public-link';
export * from './share-menu';
export * from './share-workspace';
export * from './styles';
@@ -0,0 +1,48 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
ExportToHtmlMenuItem,
ExportToMarkdownMenuItem,
ExportToPdfMenuItem,
ExportToPngMenuItem,
} from '../page-list/operation-menu-items/export';
import * as styles from './index.css';
// import type { ShareMenuProps } from './share-menu';
export const ShareExport = () => {
const t = useAFFiNEI18N();
return (
<>
<div className={styles.titleContainerStyle} style={{ fontWeight: '500' }}>
{t['com.affine.share-menu.ShareViaExport']()}
</div>
<div>
<ExportToPdfMenuItem
style={{ padding: '4px' }}
iconSize={16}
gap={'4px'}
/>
<ExportToHtmlMenuItem
style={{ padding: '4px' }}
iconSize={16}
gap={'4px'}
/>
<ExportToPngMenuItem
style={{ padding: '4px' }}
iconSize={16}
gap={'4px'}
/>
<ExportToMarkdownMenuItem
style={{ padding: '4px' }}
iconSize={16}
gap={'4px'}
/>
</div>
<div className={styles.columnContainerStyle}>
<div className={styles.descriptionStyle}>
{t['com.affine.share-menu.ShareViaExportDescription']()}
</div>
</div>
</>
);
};
@@ -1,139 +1,66 @@
import type {
AffineCloudWorkspace,
AffineOfficialWorkspace,
AffinePublicWorkspace,
LocalWorkspace,
} from '@affine/env/workspace';
import { ExportIcon, PublishIcon, ShareIcon } from '@blocksuite/icons';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { Page } from '@blocksuite/store';
import { Button } from '@toeverything/components/button';
import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public';
import { type ReactElement, useRef } from 'react';
import { useCallback, useState } from 'react';
import { Divider } from '@toeverything/components/divider';
import { useAtom } from 'jotai';
import { Menu } from '../../ui/menu/menu';
import { Export } from './export';
import { containerStyle, indicatorContainerStyle, tabStyle } from './index.css';
import * as styles from './index.css';
import { enableShareMenuAtom } from './index.jotai';
import { ShareExport } from './share-export';
import { SharePage } from './share-page';
import { ShareWorkspace } from './share-workspace';
import { StyledIndicator, TabItem } from './styles';
type SharePanel = 'SharePage' | 'Export' | 'ShareWorkspace';
type ShareMenuComponent<T> = (props: T) => ReactElement;
const MenuItems: Record<SharePanel, ShareMenuComponent<ShareMenuProps>> = {
SharePage: SharePage,
Export: Export,
ShareWorkspace: ShareWorkspace,
};
const tabIcons = {
SharePage: <ShareIcon />,
Export: <ExportIcon />,
ShareWorkspace: <PublishIcon />,
};
export interface ShareMenuProps<
Workspace extends AffineCloudWorkspace | LocalWorkspace =
Workspace extends AffineOfficialWorkspace =
| AffineCloudWorkspace
| LocalWorkspace,
| LocalWorkspace
| AffinePublicWorkspace,
> {
workspace: Workspace;
currentPage: Page;
onEnableAffineCloud: (workspace: LocalWorkspace) => void;
onOpenWorkspaceSettings: (workspace: Workspace) => void;
togglePagePublic: (page: Page, isPublic: boolean) => Promise<void>;
toggleWorkspacePublish: (
workspace: Workspace,
publish: boolean
) => Promise<void>;
}
function assertInstanceOf<T, U extends T>(
obj: T,
type: new (...args: any[]) => U
): asserts obj is U {
if (!(obj instanceof type)) {
throw new Error('Object is not instance of type');
}
useIsSharedPage: (
workspaceId: string,
pageId: string
) => [isSharePage: boolean, setIsSharePage: (enable: boolean) => void];
onEnableAffineCloud: () => void;
togglePagePublic: () => Promise<void>;
}
export const ShareMenu = (props: ShareMenuProps) => {
const [activeItem, setActiveItem] = useState<SharePanel>('SharePage');
const [isPublic] = useBlockSuiteWorkspacePageIsPublic(props.currentPage);
const [open, setOpen] = useState(false);
const containerRef = useRef<HTMLDivElement | null>(null);
const indicatorRef = useRef<HTMLDivElement | null>(null);
const startTransaction = useCallback(() => {
if (indicatorRef.current && containerRef.current) {
const indicator = indicatorRef.current;
const activeTabElement = containerRef.current.querySelector(
`[data-tab-key="${activeItem}"]`
);
assertInstanceOf(activeTabElement, HTMLElement);
requestAnimationFrame(() => {
indicator.style.left = `${activeTabElement.offsetLeft}px`;
indicator.style.width = `${activeTabElement.offsetWidth}px`;
});
}
}, [activeItem]);
const handleMenuChange = useCallback(
(selectedItem: SharePanel) => {
setActiveItem(selectedItem);
startTransaction();
},
[setActiveItem, startTransaction]
const { useIsSharedPage } = props;
const isSharedPage = useIsSharedPage(
props.workspace.id,
props.currentPage.id
);
const ActiveComponent = MenuItems[activeItem];
interface ShareMenuProps {
activeItem: SharePanel;
onChangeTab: (selectedItem: SharePanel) => void;
}
const ShareMenu = ({ activeItem, onChangeTab }: ShareMenuProps) => {
const handleButtonClick = (itemName: SharePanel) => {
onChangeTab(itemName);
setActiveItem(itemName);
};
return (
<div className={tabStyle} ref={containerRef}>
{Object.keys(MenuItems).map(item => (
<TabItem
isActive={activeItem === item}
key={item}
data-tab-key={item}
onClick={() => handleButtonClick(item as SharePanel)}
>
{tabIcons[item as SharePanel]}
{isPublic ? (item === 'SharePage' ? 'SharedPage' : item) : item}
</TabItem>
))}
const [open, setOpen] = useAtom(enableShareMenuAtom);
const t = useAFFiNEI18N();
const content = (
<div className={styles.containerStyle}>
<SharePage {...props} />
<div className={styles.columnContainerStyle}>
<Divider dividerColor="var(--affine-border-color)" size="thinner" />
</div>
);
};
const Share = (
<>
<ShareMenu activeItem={activeItem} onChangeTab={handleMenuChange} />
<div className={indicatorContainerStyle}>
<StyledIndicator
ref={(ref: HTMLDivElement | null) => {
indicatorRef.current = ref;
startTransaction();
}}
/>
</div>
<div className={containerStyle}>
<ActiveComponent {...props} />
</div>
</>
<ShareExport />
</div>
);
return (
<Menu
content={Share}
menuStyles={{
padding: '12px',
background: 'var(--affine-background-overlay-panel-color)',
transform: 'translateX(-10px)',
}}
content={content}
visible={open}
placement="bottom"
trigger={['click']}
width={439}
width={410}
disablePortal={true}
onClickAway={() => {
setOpen(false);
@@ -144,9 +71,19 @@ export const ShareMenu = (props: ShareMenuProps) => {
onClick={() => {
setOpen(!open);
}}
type={isPublic ? 'primary' : undefined}
type={'plain'}
>
<div>{isPublic ? 'Shared' : 'Share'}</div>
<div
style={{
color: isSharedPage
? 'var(--affine-link-color)'
: 'var(--affine-text-primary-color)',
}}
>
{isSharedPage
? t['com.affine.share-menu.sharedButton']()
: t['com.affine.share-menu.shareButton']()}
</div>
</Button>
</Menu>
);
@@ -1,49 +1,90 @@
import type { LocalWorkspace } from '@affine/env/workspace';
import {
Menu,
MenuItem,
MenuTrigger,
RadioButton,
RadioButtonGroup,
Switch,
} from '@affine/component';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ArrowRightSmallIcon, WebIcon } from '@blocksuite/icons';
import { Button } from '@toeverything/components/button';
import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public';
import { useState } from 'react';
import { useCallback, useMemo } from 'react';
import Input from '../../ui/input';
import { toast } from '../../ui/toast';
import { PublicLinkDisableModal } from './disable-public-link';
import {
descriptionStyle,
inputButtonRowStyle,
menuItemStyle,
} from './index.css';
import * as styles from './index.css';
import type { ShareMenuProps } from './share-menu';
import { StyledDisableButton, StyledInput, StyledLinkSpan } from './styles';
const CloudSvg = () => (
<svg
className={styles.cloudSvgStyle}
width="193"
height="108"
viewBox="0 0 193 108"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_12864_5906)">
<g opacity="0.1">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M100.707 32.803C82.4182 32.803 67.5923 47.6289 67.5923 65.9176C67.5923 68.4215 67.8692 70.8539 68.3917 73.1882C69.0964 76.3367 67.1162 79.4606 63.9681 80.1667C52.6616 82.7029 44.2173 92.8102 44.2173 104.876C44.2173 118.861 55.5547 130.199 69.5402 130.199H139.665C157.954 130.199 172.78 115.373 172.78 97.0842C172.78 78.7956 157.954 63.9696 139.665 63.9696C139.444 63.9696 139.223 63.9718 139.002 63.9762C136.18 64.0314 133.721 62.0614 133.16 59.2949C130.095 44.179 116.723 32.803 100.707 32.803ZM55.9048 65.9176C55.9048 41.1741 75.9634 21.1155 100.707 21.1155C120.758 21.1155 137.723 34.2825 143.444 52.4393C166.419 54.3582 184.467 73.6135 184.467 97.0842C184.467 121.828 164.409 141.886 139.665 141.886H69.5402C49.0999 141.886 32.5298 125.316 32.5298 104.876C32.5298 89.163 42.3171 75.7471 56.1241 70.3739C55.979 68.9069 55.9048 67.4202 55.9048 65.9176Z"
fill="var(--affine-icon-color)"
/>
</g>
</g>
<defs>
<clipPath id="clip0_12864_5906">
<rect width="193" height="108" fill="white" />
</clipPath>
</defs>
</svg>
);
export const LocalSharePage = (props: ShareMenuProps) => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
<div className={descriptionStyle}>{t['Shared Pages Description']()}</div>
<Button
type="primary"
data-testid="share-menu-enable-affine-cloud-button"
onClick={() => {
props.onEnableAffineCloud(props.workspace as LocalWorkspace);
}}
>
{t['Enable AFFiNE Cloud']()}
</Button>
</div>
<>
<div className={styles.titleContainerStyle}>
<div className={styles.shareIconStyle}>
<WebIcon />
</div>
{t['com.affine.share-menu.SharePage']()}
</div>
<div className={styles.localSharePage}>
<div className={styles.columnContainerStyle} style={{ gap: '16px' }}>
<div className={styles.descriptionStyle}>
{t['com.affine.share-menu.EnableCloudDescription']()}
</div>
<div>
<Button onClick={props.onEnableAffineCloud} type="primary">
{t['Enable AFFiNE Cloud']()}
</Button>
</div>
</div>
<div className={styles.cloudSvgContainer}></div>
<CloudSvg />
</div>
</>
);
};
export const AffineSharePage = (props: ShareMenuProps) => {
const [isPublic, setIsPublic] = useBlockSuiteWorkspacePageIsPublic(
props.currentPage
);
const {
workspace: { id: workspaceId },
currentPage: { id: pageId },
} = props;
const [isPublic, setIsPublic] = props.useIsSharedPage(workspaceId, pageId);
const [showDisable, setShowDisable] = useState(false);
const t = useAFFiNEI18N();
const sharingUrl = useMemo(() => {
return `${prefixUrl}public-workspace/${props.workspace.id}/${props.currentPage.id}`;
}, [props.workspace.id, props.currentPage.id]);
return `${runtimeConfig.serverUrlPrefix}/share/${workspaceId}/${pageId}`;
}, [workspaceId, pageId]);
const onClickCreateLink = useCallback(() => {
setIsPublic(true);
}, [setIsPublic]);
@@ -65,51 +106,126 @@ export const AffineSharePage = (props: ShareMenuProps) => {
}, [setIsPublic]);
return (
<div className={menuItemStyle}>
<div className={descriptionStyle}>
{t['Create Shared Link Description']()}
<>
<div className={styles.titleContainerStyle}>
<div className={styles.shareIconStyle}>
<WebIcon />
</div>
{t['com.affine.share-menu.SharePage']()}
</div>
<div className={inputButtonRowStyle}>
<StyledInput
type="text"
<div className={styles.titleContainerStyle} style={{ fontWeight: '500' }}>
{t['com.affine.share-menu.ShareWithLink']()}
</div>
<div className={styles.columnContainerStyle}>
<div className={styles.descriptionStyle}>
{t['com.affine.share-menu.ShareWithLinkDescription']()}
</div>
</div>
<div className={styles.rowContainerStyle}>
<Input
inputStyle={{
color: 'var(--affine-text-secondary-color)',
fontSize: 'var(--affine-font-xs)',
lineHeight: '20px',
}}
value={isPublic ? sharingUrl : `${runtimeConfig.serverUrlPrefix}/...`}
readOnly
value={isPublic ? sharingUrl : 'https://app.affine.pro/xxxx'}
/>
{!isPublic && (
{isPublic ? (
<Button onClick={onClickCopyLink} style={{ padding: '4px 12px' }}>
{t.Copy()}
</Button>
) : (
<Button
data-testid="affine-share-create-link"
onClick={onClickCreateLink}
type="primary"
style={{ padding: '4px 12px' }}
>
{t['Create']()}
</Button>
)}
{isPublic && (
<Button
data-testid="affine-share-copy-link"
onClick={onClickCopyLink}
>
{t['Copy Link']()}
{t.Create()}
</Button>
)}
</div>
<div className={descriptionStyle}>
<Trans i18nKey="Shared Pages In Public Workspace Description">
The entire Workspace is published on the web and can be edited via
<StyledLinkSpan
onClick={() => {
props.onOpenWorkspaceSettings(props.workspace);
}}
>
Workspace Settings
</StyledLinkSpan>
.
</Trans>
</div>
{isPublic && (
{runtimeConfig.enableEnhanceShareMode ? (
<div className={styles.rowContainerStyle}>
<div className={styles.subTitleStyle}>
{t['com.affine.share-menu.ShareMode']()}
</div>
<div>
<RadioButtonGroup
className={styles.radioButtonGroup}
defaultValue={'page'}
onValueChange={() => {}}
>
<RadioButton
className={styles.radioButton}
value={'page'}
spanStyle={styles.spanStyle}
>
{t['Page']()}
</RadioButton>
<RadioButton
className={styles.radioButton}
value={'edgeless'}
spanStyle={styles.spanStyle}
>
{t['Edgeless']()}
</RadioButton>
</RadioButtonGroup>
</div>
</div>
) : null}
{isPublic ? (
<>
<StyledDisableButton onClick={() => setShowDisable(true)}>
{t['Disable Public Link']()}
</StyledDisableButton>
{runtimeConfig.enableEnhanceShareMode && (
<>
<div className={styles.rowContainerStyle}>
<div className={styles.subTitleStyle}>Link expires</div>
<div>
<Menu
content={<MenuItem>Never</MenuItem>}
placement="bottom-end"
trigger="click"
>
<MenuTrigger
style={{
display: 'flex',
justifyContent: 'space-between',
padding: '4px 6px 4px 10px',
}}
>
Never
</MenuTrigger>
</Menu>
</div>
</div>
<div className={styles.rowContainerStyle}>
<div className={styles.subTitleStyle}>
{'Show "Created with AFFiNE"'}
</div>
<div>
<Switch />
</div>
</div>
<div className={styles.rowContainerStyle}>
<div className={styles.subTitleStyle}>
Search engine indexing
</div>
<div>
<Switch />
</div>
</div>
</>
)}
<div
className={styles.rowContainerStyle}
onClick={() => setShowDisable(true)}
style={{ cursor: 'pointer' }}
>
<div className={styles.disableSharePage}>
{t['Disable Public Link']()}
</div>
<ArrowRightSmallIcon />
</div>
<PublicLinkDisableModal
open={showDisable}
onConfirmDisable={onDisablePublic}
@@ -118,8 +234,8 @@ export const AffineSharePage = (props: ShareMenuProps) => {
}}
/>
</>
)}
</div>
) : null}
</>
);
};
@@ -1,67 +0,0 @@
import type {
AffineCloudWorkspace,
LocalWorkspace,
} from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Button } from '@toeverything/components/button';
import { descriptionStyle, menuItemStyle } from './index.css';
import type { ShareMenuProps } from './share-menu';
const ShareLocalWorkspace = (props: ShareMenuProps<LocalWorkspace>) => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
<div className={descriptionStyle}>
{t['Share Menu Public Workspace Description1']()}
</div>
<Button
data-testid="share-menu-enable-affine-cloud-button"
onClick={() => {
props.onOpenWorkspaceSettings(props.workspace);
}}
>
{t['Open Workspace Settings']()}
</Button>
</div>
);
};
const ShareAffineWorkspace = (props: ShareMenuProps<AffineCloudWorkspace>) => {
// fixme: regression
const isPublicWorkspace = false;
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
<div className={descriptionStyle}>
{isPublicWorkspace
? t['Share Menu Public Workspace Description2']()
: t['Share Menu Public Workspace Description1']()}
</div>
<Button
data-testid="share-menu-publish-to-web-button"
onClick={() => {
props.onOpenWorkspaceSettings(props.workspace);
}}
>
{t['Open Workspace Settings']()}
</Button>
</div>
);
};
export const ShareWorkspace = (props: ShareMenuProps) => {
if (props.workspace.flavour === WorkspaceFlavour.LOCAL) {
return (
<ShareLocalWorkspace {...(props as ShareMenuProps<LocalWorkspace>)} />
);
} else if (props.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD) {
return (
<ShareAffineWorkspace
{...(props as ShareMenuProps<AffineCloudWorkspace>)}
/>
);
}
throw new Error('Unreachable');
};