mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 14:28:51 +08:00
fix: open in app card style (#8667)
This commit is contained in:
+85
-31
@@ -2,12 +2,28 @@ import { cssVar } from '@toeverything/theme';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const width = 440;
|
||||
|
||||
export const root = style({
|
||||
background: cssVarV2('layer/background/primary'),
|
||||
borderRadius: '8px',
|
||||
border: `1px solid ${cssVarV2('layer/insideBorder/border')}`,
|
||||
cursor: 'default',
|
||||
userSelect: 'none',
|
||||
padding: '12px 10px',
|
||||
boxShadow: cssVar('shadow1'),
|
||||
display: 'flex',
|
||||
gap: 8,
|
||||
position: 'fixed',
|
||||
bottom: 16,
|
||||
left: `calc(50dvw - ${width / 2}px)`,
|
||||
width,
|
||||
zIndex: cssVar('zIndexPopover'),
|
||||
transition: 'transform 0.2s ease-in-out',
|
||||
selectors: {
|
||||
'&[data-hidden="true"]': {
|
||||
transform: 'translateY(200%)',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const pane = style({
|
||||
@@ -22,48 +38,86 @@ export const pane = style({
|
||||
},
|
||||
});
|
||||
|
||||
export const row = style({
|
||||
fontSize: cssVar('fontSm'),
|
||||
fontWeight: 400,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
columnGap: 10,
|
||||
color: cssVarV2('text/secondary'),
|
||||
});
|
||||
|
||||
export const clickableRow = style([
|
||||
row,
|
||||
{
|
||||
cursor: 'pointer',
|
||||
},
|
||||
]);
|
||||
|
||||
export const buttonGroup = style({
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
justifyContent: 'flex-end',
|
||||
});
|
||||
|
||||
export const button = style({
|
||||
height: 26,
|
||||
borderRadius: 4,
|
||||
padding: '0 8px',
|
||||
borderRadius: 8,
|
||||
padding: '0 12px',
|
||||
fontSize: cssVar('fontXs'),
|
||||
});
|
||||
|
||||
export const primaryRow = style([
|
||||
row,
|
||||
{
|
||||
color: cssVarV2('text/primary'),
|
||||
},
|
||||
]);
|
||||
export const titleRow = style({
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
fontSize: cssVar('fontSm'),
|
||||
color: cssVarV2('text/primary'),
|
||||
fontWeight: 500,
|
||||
});
|
||||
|
||||
export const icon = style({
|
||||
export const subtitleRow = style({
|
||||
fontSize: cssVar('fontXs'),
|
||||
color: cssVarV2('text/primary'),
|
||||
marginTop: 4,
|
||||
});
|
||||
|
||||
export const controlsRow = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginTop: 8,
|
||||
});
|
||||
|
||||
export const rememberLabel = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
fontWeight: 500,
|
||||
fontSize: cssVar('fontXs'),
|
||||
cursor: 'pointer',
|
||||
});
|
||||
|
||||
export const rememberCheckbox = style({
|
||||
width: 20,
|
||||
height: 20,
|
||||
flexShrink: 0,
|
||||
fontSize: 20,
|
||||
selectors: {
|
||||
[`${primaryRow} &`]: {
|
||||
color: cssVarV2('icon/activated'),
|
||||
},
|
||||
},
|
||||
color: cssVarV2('icon/primary'),
|
||||
});
|
||||
|
||||
export const closeButton = style({
|
||||
width: 24,
|
||||
height: 24,
|
||||
flexShrink: 0,
|
||||
fontSize: 24,
|
||||
});
|
||||
|
||||
export const contentCol = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-start',
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export const appIconCol = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-start',
|
||||
});
|
||||
|
||||
export const appIcon = style({
|
||||
width: 48,
|
||||
height: 48,
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const spacer = style({
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
export const link = style({
|
||||
color: cssVarV2('text/link'),
|
||||
textDecoration: 'underline',
|
||||
});
|
||||
|
||||
+52
-45
@@ -1,18 +1,17 @@
|
||||
import { Button, Checkbox } from '@affine/component';
|
||||
import { Button, Checkbox, IconButton } from '@affine/component';
|
||||
import {
|
||||
OpenInAppService,
|
||||
OpenLinkMode,
|
||||
} from '@affine/core/modules/open-in-app';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { DownloadIcon, LocalWorkspaceIcon } from '@blocksuite/icons/rc';
|
||||
import { appIconMap } from '@affine/core/utils';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { CloseIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import * as styles from './open-in-app-card.css';
|
||||
|
||||
export const OpenInAppCard = ({ className }: { className?: string }) => {
|
||||
export const OpenInAppCard = () => {
|
||||
const openInAppService = useService(OpenInAppService);
|
||||
const show = useLiveData(openInAppService.showOpenInAppBanner$);
|
||||
const t = useI18n();
|
||||
@@ -22,7 +21,7 @@ export const OpenInAppCard = ({ className }: { className?: string }) => {
|
||||
const onOpen = useCallback(() => {
|
||||
openInAppService.showOpenInAppPage();
|
||||
if (remember) {
|
||||
openInAppService.setOpenLinkMode(OpenLinkMode.OPEN_IN_DESKTOP_APP);
|
||||
openInAppService.dismissBanner(OpenLinkMode.OPEN_IN_DESKTOP_APP);
|
||||
}
|
||||
}, [openInAppService, remember]);
|
||||
|
||||
@@ -36,34 +35,48 @@ export const OpenInAppCard = ({ className }: { className?: string }) => {
|
||||
setRemember(v => !v);
|
||||
}, []);
|
||||
|
||||
const handleDownload = useCallback(() => {
|
||||
track.$.navigationPanel.bottomButtons.downloadApp();
|
||||
const url = `https://affine.pro/download?channel=stable`;
|
||||
open(url, '_blank');
|
||||
}, []);
|
||||
|
||||
if (!show) {
|
||||
return null;
|
||||
}
|
||||
const appIcon = appIconMap[BUILD_CONFIG.appBuildType];
|
||||
|
||||
return (
|
||||
<div className={clsx(styles.root, className)}>
|
||||
<div className={styles.pane}>
|
||||
<div className={styles.primaryRow}>
|
||||
<LocalWorkspaceIcon className={styles.icon} />
|
||||
<div>{t.t('com.affine.open-in-app.card.title')}</div>
|
||||
<div className={styles.root} data-hidden={!show}>
|
||||
<div className={styles.appIconCol}>
|
||||
<img src={appIcon} alt="app icon" width={48} height={48} />
|
||||
</div>
|
||||
<div className={styles.contentCol}>
|
||||
<div className={styles.titleRow}>
|
||||
{t.t('com.affine.open-in-app.card.title')}
|
||||
<div className={styles.spacer} />
|
||||
<IconButton
|
||||
className={styles.closeButton}
|
||||
icon={<CloseIcon />}
|
||||
onClick={onDismiss}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.icon}>{/* placeholder */}</div>
|
||||
<div className={styles.buttonGroup}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="custom"
|
||||
className={styles.button}
|
||||
onClick={onOpen}
|
||||
<div className={styles.subtitleRow}>
|
||||
<Trans i18nKey="com.affine.open-in-app.card.subtitle">
|
||||
No desktop app?
|
||||
<a
|
||||
href="https://affine.pro/download"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={styles.link}
|
||||
>
|
||||
{t.t('com.affine.open-in-app.card.button.open')}
|
||||
</Button>
|
||||
Click to download
|
||||
</a>
|
||||
.
|
||||
</Trans>
|
||||
</div>
|
||||
<div className={styles.controlsRow}>
|
||||
<label className={styles.rememberLabel}>
|
||||
<Checkbox
|
||||
className={styles.rememberCheckbox}
|
||||
checked={remember}
|
||||
onChange={onToggleRemember}
|
||||
/>
|
||||
{t.t('com.affine.open-in-app.card.remember')}
|
||||
</label>
|
||||
<div className={styles.spacer} />
|
||||
<div className={styles.buttonGroup}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="custom"
|
||||
@@ -72,23 +85,17 @@ export const OpenInAppCard = ({ className }: { className?: string }) => {
|
||||
>
|
||||
{t.t('com.affine.open-in-app.card.button.dismiss')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="custom"
|
||||
className={styles.button}
|
||||
onClick={onOpen}
|
||||
>
|
||||
{t.t('com.affine.open-in-app.card.button.open')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.pane}>
|
||||
<div className={styles.clickableRow} onClick={onToggleRemember}>
|
||||
<Checkbox className={styles.icon} checked={remember} />
|
||||
<div>{t.t('com.affine.open-in-app.card.remember')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.pane}>
|
||||
<div className={styles.clickableRow} onClick={handleDownload}>
|
||||
<DownloadIcon className={styles.icon} />
|
||||
<div>{t.t('com.affine.open-in-app.card.download')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user