mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-22 09:51:35 +03:00
feat(core): adjust share menu style (#4584)
This commit is contained in:
parent
ae4322b75f
commit
5ebd82dc04
@ -4,7 +4,7 @@ import {
|
||||
WorkspaceFlavour,
|
||||
} from '@affine/env/workspace';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { useExportPage } from '../../../hooks/affine/use-export-page';
|
||||
import { useIsSharedPage } from '../../../hooks/affine/use-is-shared-page';
|
||||
@ -20,6 +20,17 @@ export const SharePageModal = ({ workspace, page }: SharePageModalProps) => {
|
||||
const onTransformWorkspace = useOnTransformWorkspace();
|
||||
const [open, setOpen] = useState(false);
|
||||
const exportHandler = useExportPage(page);
|
||||
const handleConfirm = useCallback(() => {
|
||||
if (workspace.flavour !== WorkspaceFlavour.LOCAL) {
|
||||
return;
|
||||
}
|
||||
onTransformWorkspace(
|
||||
WorkspaceFlavour.LOCAL,
|
||||
WorkspaceFlavour.AFFINE_CLOUD,
|
||||
workspace
|
||||
);
|
||||
setOpen(false);
|
||||
}, [onTransformWorkspace, workspace]);
|
||||
return (
|
||||
<>
|
||||
<ShareMenu
|
||||
@ -34,14 +45,7 @@ export const SharePageModal = ({ workspace, page }: SharePageModalProps) => {
|
||||
<EnableAffineCloudModal
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
onConfirm={() => {
|
||||
onTransformWorkspace(
|
||||
WorkspaceFlavour.LOCAL,
|
||||
WorkspaceFlavour.AFFINE_CLOUD,
|
||||
workspace
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
|
@ -7,9 +7,9 @@ import {
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import type { Collection } from '@affine/env/filter';
|
||||
import type { PropertiesMeta } from '@affine/env/filter';
|
||||
import {
|
||||
import type {
|
||||
WorkspaceFlavour,
|
||||
type WorkspaceHeaderProps,
|
||||
WorkspaceHeaderProps,
|
||||
} from '@affine/env/workspace';
|
||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||
import { useSetAtom } from 'jotai/react';
|
||||
@ -130,15 +130,12 @@ export function WorkspaceHeader({
|
||||
|
||||
// route in edit page
|
||||
if ('pageId' in currentEntry) {
|
||||
const isCloudWorkspace =
|
||||
currentWorkspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
|
||||
const currentPage = currentWorkspace.blockSuiteWorkspace.getPage(
|
||||
currentEntry.pageId
|
||||
);
|
||||
const sharePageModal =
|
||||
isCloudWorkspace && currentPage ? (
|
||||
<SharePageModal workspace={currentWorkspace} page={currentPage} />
|
||||
) : null;
|
||||
const sharePageModal = currentPage ? (
|
||||
<SharePageModal workspace={currentWorkspace} page={currentPage} />
|
||||
) : null;
|
||||
return (
|
||||
<Header
|
||||
mainContainerAtom={mainContainerAtom}
|
||||
|
@ -1,5 +1,22 @@
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
|
||||
export const headerStyle = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
fontWeight: 600,
|
||||
lineHeight: '22px',
|
||||
padding: '0 4px',
|
||||
gap: '4px',
|
||||
});
|
||||
|
||||
export const menuStyle = style({
|
||||
width: '410px',
|
||||
height: 'auto',
|
||||
padding: '12px',
|
||||
transform: 'translateX(-10px)',
|
||||
});
|
||||
|
||||
export const menuItemStyle = style({
|
||||
padding: '4px',
|
||||
transition: 'all 0.3s',
|
||||
@ -12,7 +29,7 @@ export const descriptionStyle = style({
|
||||
lineHeight: '20px',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
textAlign: 'left',
|
||||
padding: '0 2px',
|
||||
padding: '0 6px',
|
||||
});
|
||||
|
||||
export const buttonStyle = style({
|
||||
@ -51,10 +68,11 @@ export const titleContainerStyle = style({
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
fontWeight: 600,
|
||||
fontWeight: 500,
|
||||
lineHeight: '22px',
|
||||
padding: '0 4px',
|
||||
});
|
||||
|
||||
export const subTitleStyle = style({
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
fontWeight: 500,
|
||||
@ -65,7 +83,6 @@ export const columnContainerStyle = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
padding: '0 4px',
|
||||
width: '100%',
|
||||
gap: '8px',
|
||||
});
|
||||
@ -109,22 +126,18 @@ export const localSharePage = style({
|
||||
alignItems: 'center',
|
||||
borderRadius: '8px',
|
||||
backgroundColor: 'var(--affine-background-secondary-color)',
|
||||
minHeight: '108px',
|
||||
minHeight: '84px',
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
export const cloudSvgContainer = style({
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
minWidth: '185px',
|
||||
});
|
||||
|
||||
export const cloudSvgStyle = style({
|
||||
width: '193px',
|
||||
height: '108px',
|
||||
width: '146px',
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
position: 'absolute',
|
||||
bottom: '0',
|
||||
right: '8px',
|
||||
right: '0',
|
||||
});
|
||||
export const shareIconStyle = style({
|
||||
fontSize: '16px',
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { LinkIcon } from '@blocksuite/icons';
|
||||
import { Button } from '@toeverything/components/button';
|
||||
@ -24,31 +25,39 @@ export const ShareExport = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.titleContainerStyle} style={{ fontWeight: '500' }}>
|
||||
<div className={styles.titleContainerStyle}>
|
||||
{t['com.affine.share-menu.ShareViaExport']()}
|
||||
</div>
|
||||
<div className={styles.descriptionStyle}>
|
||||
{t['com.affine.share-menu.ShareViaExportDescription']()}
|
||||
</div>
|
||||
<div>
|
||||
<ExportMenuItems
|
||||
exportHandler={exportHandler}
|
||||
className={styles.menuItemStyle}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.columnContainerStyle}>
|
||||
<div className={styles.descriptionStyle}>
|
||||
{t['com.affine.share-menu.ShareViaExportDescription']()}
|
||||
{workspace.flavour !== WorkspaceFlavour.LOCAL ? (
|
||||
<div className={styles.columnContainerStyle}>
|
||||
<Divider size="thinner" />
|
||||
<div className={styles.titleContainerStyle}>
|
||||
{t['com.affine.share-menu.share-privately']()}
|
||||
</div>
|
||||
<div className={styles.descriptionStyle}>
|
||||
{t['com.affine.share-menu.share-privately.description']()}
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
className={styles.shareLinkStyle}
|
||||
onClick={onClickCopyLink}
|
||||
icon={<LinkIcon />}
|
||||
type="plain"
|
||||
>
|
||||
{t['com.affine.share-menu.copy-private-link']()}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Divider size="thinner" />
|
||||
<div>
|
||||
<Button
|
||||
className={styles.shareLinkStyle}
|
||||
onClick={onClickCopyLink}
|
||||
icon={<LinkIcon />}
|
||||
type="plain"
|
||||
>
|
||||
{t['Copy Link']()}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,10 +1,12 @@
|
||||
import type {
|
||||
AffineCloudWorkspace,
|
||||
AffineOfficialWorkspace,
|
||||
AffinePublicWorkspace,
|
||||
LocalWorkspace,
|
||||
import {
|
||||
type AffineCloudWorkspace,
|
||||
type AffineOfficialWorkspace,
|
||||
type AffinePublicWorkspace,
|
||||
type LocalWorkspace,
|
||||
WorkspaceFlavour,
|
||||
} from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { WebIcon } from '@blocksuite/icons';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { Button } from '@toeverything/components/button';
|
||||
import { Divider } from '@toeverything/components/divider';
|
||||
@ -30,15 +32,16 @@ export interface ShareMenuProps<
|
||||
exportHandler: (type: 'pdf' | 'html' | 'png' | 'markdown') => Promise<void>;
|
||||
}
|
||||
|
||||
export const ShareMenu = (props: ShareMenuProps) => {
|
||||
const { useIsSharedPage } = props;
|
||||
const [isSharedPage] = useIsSharedPage(
|
||||
props.workspace.id,
|
||||
props.currentPage.id
|
||||
);
|
||||
const ShareMenuContent = (props: ShareMenuProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const content = (
|
||||
return (
|
||||
<div className={styles.containerStyle}>
|
||||
<div className={styles.headerStyle}>
|
||||
<div className={styles.shareIconStyle}>
|
||||
<WebIcon />
|
||||
</div>
|
||||
{t['com.affine.share-menu.SharePage']()}
|
||||
</div>
|
||||
<SharePage {...props} />
|
||||
<div className={styles.columnContainerStyle}>
|
||||
<Divider size="thinner" />
|
||||
@ -46,22 +49,48 @@ export const ShareMenu = (props: ShareMenuProps) => {
|
||||
<ShareExport {...props} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const LocalShareMenu = (props: ShareMenuProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
return (
|
||||
<Menu
|
||||
items={content}
|
||||
items={<ShareMenuContent {...props} />}
|
||||
contentOptions={{
|
||||
style: {
|
||||
width: '410px',
|
||||
height: 'auto',
|
||||
padding: '12px',
|
||||
transform: 'translateX(-10px)',
|
||||
},
|
||||
className: styles.menuStyle,
|
||||
}}
|
||||
rootOptions={{
|
||||
modal: false,
|
||||
}}
|
||||
>
|
||||
<Button data-testid="share-menu-button" type="plain">
|
||||
<Button data-testid="local-share-menu-button" type="plain">
|
||||
{t['com.affine.share-menu.shareButton']()}
|
||||
</Button>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const CloudShareMenu = (props: ShareMenuProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const { workspace, currentPage, useIsSharedPage } = props;
|
||||
const [isSharedPage] = useIsSharedPage(workspace.id, currentPage.id);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
items={<ShareMenuContent {...props} />}
|
||||
contentOptions={{
|
||||
className: styles.menuStyle,
|
||||
}}
|
||||
rootOptions={{
|
||||
modal: false,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
data-testid="cloud-share-menu-button"
|
||||
type="plain"
|
||||
onClick={() => console.log('gg')}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: isSharedPage
|
||||
@ -77,3 +106,12 @@ export const ShareMenu = (props: ShareMenuProps) => {
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
export const ShareMenu = (props: ShareMenuProps) => {
|
||||
const { workspace } = props;
|
||||
|
||||
if (workspace.flavour === WorkspaceFlavour.LOCAL) {
|
||||
return <LocalShareMenu {...props} />;
|
||||
}
|
||||
return <CloudShareMenu {...props} />;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ArrowRightSmallIcon, WebIcon } from '@blocksuite/icons';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||
import { Button } from '@toeverything/components/button';
|
||||
import { Menu, MenuItem, MenuTrigger } from '@toeverything/components/menu';
|
||||
import { useState } from 'react';
|
||||
@ -17,28 +17,20 @@ import { useSharingUrl } from './use-share-url';
|
||||
|
||||
const CloudSvg = () => (
|
||||
<svg
|
||||
className={styles.cloudSvgStyle}
|
||||
width="193"
|
||||
height="108"
|
||||
viewBox="0 0 193 108"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="146"
|
||||
height="84"
|
||||
viewBox="0 0 146 84"
|
||||
fill="none"
|
||||
>
|
||||
<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 opacity="0.1">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M66.9181 15.9788C52.6393 15.9788 41.064 27.5541 41.064 41.8329C41.064 43.7879 41.2801 45.687 41.6881 47.5094C42.2383 49.9676 40.6923 52.4066 38.2344 52.9579C29.4068 54.938 22.814 62.8293 22.814 72.2496C22.814 83.1687 31.6657 92.0204 42.5848 92.0204H97.3348C111.614 92.0204 123.189 80.4451 123.189 66.1663C123.189 51.8874 111.614 40.3121 97.3348 40.3121C97.1618 40.3121 96.9892 40.3138 96.8169 40.3172C94.6134 40.3603 92.6941 38.8222 92.2561 36.6623C89.8629 24.8606 79.4226 15.9788 66.9181 15.9788ZM31.939 41.8329C31.939 22.5145 47.5997 6.85376 66.9181 6.85376C82.573 6.85376 95.8181 17.1339 100.285 31.3098C118.223 32.808 132.314 47.8415 132.314 66.1663C132.314 85.4847 116.653 101.145 97.3348 101.145H42.5848C26.6261 101.145 13.689 88.2083 13.689 72.2496C13.689 59.9818 21.3304 49.5073 32.1102 45.3122C31.9969 44.1668 31.939 43.0061 31.939 41.8329Z"
|
||||
fill="var(--affine-icon-color)"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_12864_5906">
|
||||
<rect width="193" height="108" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@ -47,25 +39,27 @@ export const LocalSharePage = (props: ShareMenuProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<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}>
|
||||
<div className={styles.columnContainerStyle} style={{ gap: '12px' }}>
|
||||
<div
|
||||
className={styles.descriptionStyle}
|
||||
style={{ maxWidth: '230px' }}
|
||||
>
|
||||
{t['com.affine.share-menu.EnableCloudDescription']()}
|
||||
</div>
|
||||
<div>
|
||||
<Button onClick={props.onEnableAffineCloud} type="primary">
|
||||
<Button
|
||||
onClick={props.onEnableAffineCloud}
|
||||
type="primary"
|
||||
data-testid="share-menu-enable-affine-cloud-button"
|
||||
>
|
||||
{t['Enable AFFiNE Cloud']()}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.cloudSvgContainer}></div>
|
||||
<CloudSvg />
|
||||
<div className={styles.cloudSvgContainer}>
|
||||
<CloudSvg />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
@ -100,17 +94,11 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.titleContainerStyle}>
|
||||
<div className={styles.shareIconStyle}>
|
||||
<WebIcon />
|
||||
</div>
|
||||
{t['com.affine.share-menu.SharePage']()}
|
||||
</div>
|
||||
<div className={styles.titleContainerStyle} style={{ fontWeight: '500' }}>
|
||||
{t['com.affine.share-menu.ShareWithLink']()}
|
||||
{t['com.affine.share-menu.publish-to-web']()}
|
||||
</div>
|
||||
<div className={styles.columnContainerStyle}>
|
||||
<div className={styles.descriptionStyle}>
|
||||
{t['com.affine.share-menu.ShareWithLinkDescription']()}
|
||||
{t['com.affine.share-menu.publish-to-web.description']()}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.rowContainerStyle}>
|
||||
|
@ -313,7 +313,7 @@
|
||||
"com.affine.settingSidebar.settings.general": "General",
|
||||
"com.affine.settingSidebar.settings.workspace": "Workspace",
|
||||
"com.affine.settingSidebar.title": "Settings",
|
||||
"com.affine.share-menu.EnableCloudDescription": "Sharing page publicly requires AFFiNE Cloud service.",
|
||||
"com.affine.share-menu.EnableCloudDescription": "Sharing page requires AFFiNE Cloud.",
|
||||
"com.affine.share-menu.shareButton": "Share",
|
||||
"com.affine.share-menu.sharedButton": "Shared",
|
||||
"com.affine.share-menu.SharedPage": "Shared Page",
|
||||
@ -628,5 +628,10 @@
|
||||
"com.affine.cmdk.affine.whats-new": "What's New",
|
||||
"com.affine.cmdk.affine.getting-started": "Getting Started",
|
||||
"com.affine.cmdk.affine.contact-us": "Contact Us",
|
||||
"com.affine.cmdk.affine.restart-to-upgrade": "Restart to Upgrade"
|
||||
"com.affine.cmdk.affine.restart-to-upgrade": "Restart to Upgrade",
|
||||
"com.affine.share-menu.publish-to-web": "Publish to Web",
|
||||
"com.affine.share-menu.publish-to-web.description": "Let anyone with a link view a read-only version of this page.",
|
||||
"com.affine.share-menu.share-privately": "Share Privately",
|
||||
"com.affine.share-menu.share-privately.description": "Only members of this Workspace can open this link.",
|
||||
"com.affine.share-menu.copy-private-link": "Copy Private Link"
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
addUserToWorkspace,
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
enableCloudWorkspaceFromShareButton,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import {
|
||||
@ -47,14 +48,14 @@ test.describe('collaboration', () => {
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
await enableCloudWorkspaceFromShareButton(page);
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.pressSequentially('TEST TITLE', {
|
||||
delay: 50,
|
||||
});
|
||||
await page.keyboard.press('Enter', { delay: 50 });
|
||||
await page.keyboard.type('TEST CONTENT', { delay: 50 });
|
||||
await page.getByTestId('share-menu-button').click();
|
||||
await page.getByTestId('cloud-share-menu-button').click();
|
||||
await page.getByTestId('share-menu-create-link-button').click();
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
|
||||
|
@ -176,3 +176,12 @@ export async function enableCloudWorkspace(page: Page) {
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
}
|
||||
export async function enableCloudWorkspaceFromShareButton(page: Page) {
|
||||
await page.getByTestId('local-share-menu-button').click();
|
||||
await page.getByTestId('share-menu-enable-affine-cloud-button').click();
|
||||
await page.getByTestId('confirm-enable-affine-cloud-button').click();
|
||||
// wait for upload and delete local workspace
|
||||
await page.waitForTimeout(2000);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user