Compare commits

..

12 Commits

Author SHA1 Message Date
Alex Yang
36bd0b02d0 v0.8.0-canary.11 2023-08-04 17:34:31 -07:00
JimmFly
3a92c4f798 feat: modify sidebar floating logic and header responsive style (#3550) 2023-08-05 00:15:17 +00:00
Alex Yang
97de0ef5b4 build: use tsconfig bundler (#3581) 2023-08-05 00:00:36 +00:00
Alex Yang
bbf5f0efe0 chore: bump version (#3567) 2023-08-04 23:55:28 +00:00
Alex Yang
ea76936508 feat: update 404 page (#3580)
Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com>
2023-08-04 23:11:30 +00:00
Alex Yang
f076cb0ead docs: fix all-contributors count 2023-08-04 13:48:43 -07:00
fossabot
0f230253a8 docs: add license scan report and status (#3576)
Co-authored-by: Alex Yang <himself65@outlook.com>
2023-08-04 13:44:15 -07:00
Alex Yang
13d2dde501 fix: only run migration in local workspace (#3570) 2023-08-04 16:09:55 +00:00
Garfield Lee
65fc0ed59c refactor: remove React.FC for component package (#3575) 2023-08-04 15:00:28 +00:00
Chi Zhang
7ec4b8fb8c Update README.md (#3578) 2023-08-04 14:46:10 +00:00
Peng Xiao
6415f0093b fix: optimize types for infra/electron (#3574) 2023-08-04 09:23:56 +00:00
LongYinan
5795020403 style: add no-misused-promises rule (#3547)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
2023-08-04 08:08:10 +00:00
121 changed files with 1145 additions and 1073 deletions

View File

@@ -214,6 +214,7 @@ const config = {
ignoreIIFE: false,
},
],
'@typescript-eslint/no-misused-promises': ['error'],
},
})),
{
@@ -239,6 +240,7 @@ const config = {
},
],
'@typescript-eslint/no-floating-promises': 0,
'@typescript-eslint/no-misused-promises': 0,
},
},
],

View File

@@ -14,15 +14,6 @@
</div>
<div align="center">
<!--
Make New Badge Pattern badges inline
See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066
-->
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[all-contributors-badge]: https://img.shields.io/badge/all_contributors-66-orange.svg?style=flat-square
<!-- ALL-CONTRIBUTORS-BADGE:END -->
[![AFFiNE Web](<https://img.shields.io/badge/-Try%20It%20Online%20%E2%86%92-rgb(84,56,255)?style=flat-square&logoColor=white&logo=affine>)](https://app.affine.pro)
[![AFFiNE macOS M1/M2 Chip](https://img.shields.io/badge/-macOS_M_Chip%20%E2%86%92-black?style=flat-square&logo=apple&logoColor=white)](https://affine.pro/download)
@@ -39,6 +30,7 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066
[![React-version-icon]](https://reactjs.org/)
[![blocksuite-icon]](https://github.com/toeverything/blocksuite)
[![Rust-version-icon]](https://www.rust-lang.org/)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftoeverything%2FAFFiNE.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftoeverything%2FAFFiNE?ref=badge_shield)
</div>
@@ -191,6 +183,7 @@ See [docs/contributing/tutorial.md](./docs/contributing/tutorial.md) for details
See [LICENSE] for details.
[all-contributors-badge]: https://img.shields.io/github/all-contributors/toeverything/AFFiNE/master?color=orange
[license]: ./LICENSE
[building.md]: ./docs/BUILDING.md
[these people]: https://twitter.com/AffineOfficial/followers
@@ -205,3 +198,5 @@ See [LICENSE] for details.
[typescript-version-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/affine/dev/typescript
[react-version-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/AFFiNE/react?filename=apps%2Fcore%2Fpackage.json&color=rgb(97%2C228%2C251)
[blocksuite-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/AFFiNE/@blocksuite/store?color=6880ff&filename=apps%2Fcore%2Fpackage.json&label=blocksuite
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftoeverything%2FAFFiNE.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftoeverything%2FAFFiNE?ref=badge_large)

View File

@@ -2,7 +2,7 @@
"name": "@affine/core",
"type": "module",
"private": true,
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"scripts": {
"build": "yarn -T run build-core",
"dev": "yarn -T run dev-core",
@@ -18,13 +18,13 @@
"@affine/jotai": "workspace:*",
"@affine/templates": "workspace:*",
"@affine/workspace": "workspace:*",
"@blocksuite/block-std": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/block-std": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/icons": "^2.1.29",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2",
"@emotion/cache": "^11.11.0",
@@ -33,6 +33,7 @@
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.2",
"@react-hookz/web": "^23.1.0",
"@toeverything/components": "^0.0.6",
"async-call-rpc": "^6.3.1",
"cmdk": "^0.2.0",
"css-spring": "^4.1.0",

View File

@@ -1,5 +1,6 @@
import '@affine/component/theme/global.css';
import '@affine/component/theme/theme.css';
import '@toeverything/components/style.css';
import { AffineContext } from '@affine/component/context';
import { WorkspaceFallback } from '@affine/component/workspace';

View File

@@ -1,5 +1,7 @@
import type { PrimitiveAtom } from 'jotai';
import { atom } from 'jotai';
import { atomFamily, atomWithStorage } from 'jotai/utils';
import type { AtomFamily } from 'jotai/vanilla/utils/atomFamily';
import type { CreateWorkspaceMode } from '../components/affine/create-workspace-modal';
import type { SettingProps } from '../components/affine/setting-modal';
@@ -59,19 +61,16 @@ const defaultPageSetting = {
mode: 'page',
} satisfies PageLocalSetting;
export const pageSettingFamily = atomFamily((pageId: string) =>
export const pageSettingFamily: AtomFamily<
string,
PrimitiveAtom<PageLocalSetting>
> = atomFamily((pageId: string) =>
atom(
get =>
get(pageSettingsBaseAtom)[pageId] ?? {
...defaultPageSetting,
},
(
get,
set,
patch:
| Partial<PageLocalSetting>
| ((prevSetting: PageLocalSetting | undefined) => void)
) => {
(get, set, patch) => {
set(recentPageSettingsBaseAtom, ids => {
// pick 3 recent page ids
return [...new Set([pageId, ...ids]).values()].slice(0, 3);

View File

@@ -36,15 +36,15 @@ async function tryMigration() {
const adapter = WorkspaceAdapters[oldMeta.flavour];
assertExists(adapter);
const upgrade = async () => {
if (oldMeta.flavour !== WorkspaceFlavour.LOCAL) {
console.warn('not supported');
return;
}
const workspace = await adapter.CRUD.get(oldMeta.id);
if (!workspace) {
console.warn('cannot find workspace', oldMeta.id);
return;
}
if (workspace.flavour !== WorkspaceFlavour.LOCAL) {
console.warn('not supported');
return;
}
const doc = workspace.blockSuiteWorkspace.doc;
const provider = createIndexedDBDownloadProvider(
workspace.id,
@@ -83,11 +83,14 @@ async function tryMigration() {
// create a new workspace and push it to metadata
promises.push(upgrade());
} else if (oldMeta.version < WorkspaceVersion.DatabaseV3) {
console.log('migrate to v3');
const adapter = WorkspaceAdapters[oldMeta.flavour];
assertExists(adapter);
promises.push(
(async () => {
if (oldMeta.flavour !== WorkspaceFlavour.LOCAL) {
console.warn('not supported');
return;
}
const workspace = await adapter.CRUD.get(oldMeta.id);
if (workspace) {
const provider = createIndexedDBDownloadProvider(
@@ -107,11 +110,11 @@ async function tryMigration() {
const index = newMetadata.findIndex(
meta => meta.id === oldMeta.id
);
console.log('migrate to v3');
newMetadata[index] = {
...oldMeta,
version: WorkspaceVersion.DatabaseV3,
};
console.log('migrate to v3');
})()
);
}
@@ -121,8 +124,8 @@ async function tryMigration() {
.then(() => {
console.log('migration done');
})
.catch(() => {
console.error('migration failed');
.catch(e => {
console.error('migration failed', e);
})
.finally(() => {
localStorage.setItem('jotai-workspaces', JSON.stringify(newMetadata));

View File

@@ -139,7 +139,6 @@ const SetDBLocationContent = ({
if (result?.filePath) {
onConfirmLocation(result.filePath);
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic so the type is unknown
toast(t[result.error]());
}
})().catch(err => {
@@ -273,7 +272,6 @@ export const CreateWorkspaceModal = ({
setStep('set-syncing-mode');
} else if (result.error || result.canceled) {
if (result.error) {
// @ts-expect-error: result.error is dynamic so the type is unknown
toast(t[result.error]());
}
onClose();

View File

@@ -36,7 +36,6 @@ export const ExportPanel: FC<{
await syncBlobsToSqliteDb(workspace);
const result = await window.apis?.dialog.saveDBFileAs(workspaceId);
if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
} else if (!result?.canceled) {
toast(t['Export success']());

View File

@@ -55,7 +55,6 @@ export const StoragePanel: FC<{
if (!result?.error && !result?.canceled) {
toast(t['Move folder success']());
} else if (result?.error) {
// @ts-expect-error: result.error is dynamic
toast(t[result.error]());
}
})

View File

@@ -8,6 +8,7 @@ import { isDesktop } from '@affine/env/constant';
import { CloseIcon, MinusIcon, RoundedRectangleIcon } from '@blocksuite/icons';
import type { Page } from '@blocksuite/store';
import { headerItemsAtom } from '@toeverything/infra/atom';
import clsx from 'clsx';
import { useAtom, useAtomValue } from 'jotai';
import type { FC, HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
import {
@@ -38,8 +39,6 @@ export type BaseHeaderProps<
export enum HeaderRightItemName {
EditorOptionMenu = 'editorOptionMenu',
// some windows only items
WindowsAppControls = 'windowsAppControls',
}
type HeaderItem = {
@@ -63,59 +62,54 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
);
},
},
[HeaderRightItemName.WindowsAppControls]: {
Component: () => {
const handleMinimizeApp = useCallback(() => {
window.apis?.ui.handleMinimizeApp().catch(err => {
console.error(err);
});
}, []);
const handleMaximizeApp = useCallback(() => {
window.apis?.ui.handleMaximizeApp().catch(err => {
console.error(err);
});
}, []);
const handleCloseApp = useCallback(() => {
window.apis?.ui.handleCloseApp().catch(err => {
console.error(err);
});
}, []);
return (
<div
data-platform-target="win32"
className={styles.windowAppControlsWrapper}
>
<button
data-type="minimize"
className={styles.windowAppControl}
onClick={handleMinimizeApp}
>
<MinusIcon />
</button>
<button
data-type="maximize"
className={styles.windowAppControl}
onClick={handleMaximizeApp}
>
<RoundedRectangleIcon />
</button>
<button
data-type="close"
className={styles.windowAppControl}
onClick={handleCloseApp}
>
<CloseIcon />
</button>
</div>
);
},
availableWhen: () => {
return isDesktop && globalThis.platform === 'win32';
},
},
};
export type HeaderProps = BaseHeaderProps;
const WindowsAppControls = () => {
const handleMinimizeApp = useCallback(() => {
window.apis?.ui.handleMinimizeApp().catch(err => {
console.error(err);
});
}, []);
const handleMaximizeApp = useCallback(() => {
window.apis?.ui.handleMaximizeApp().catch(err => {
console.error(err);
});
}, []);
const handleCloseApp = useCallback(() => {
window.apis?.ui.handleCloseApp().catch(err => {
console.error(err);
});
}, []);
return (
<div
data-platform-target="win32"
className={styles.windowAppControlsWrapper}
>
<button
data-type="minimize"
className={styles.windowAppControl}
onClick={handleMinimizeApp}
>
<MinusIcon />
</button>
<button
data-type="maximize"
className={styles.windowAppControl}
onClick={handleMaximizeApp}
>
<RoundedRectangleIcon />
</button>
<button
data-type="close"
className={styles.windowAppControl}
onClick={handleCloseApp}
>
<CloseIcon />
</button>
</div>
);
};
const PluginHeader = () => {
const rootRef = useRef<HTMLDivElement>(null);
@@ -165,7 +159,7 @@ export const Header = forwardRef<
const appSidebarFloating = useAtomValue(appSidebarFloatingAtom);
const mode = useAtomValue(currentModeAtom);
const isWindowsDesktop = globalThis.platform === 'win32' && isDesktop;
return (
<div
className={styles.headerContainer}
@@ -196,14 +190,25 @@ export const Header = forwardRef<
data-has-warning={showWarning}
data-testid="editor-header-items"
data-is-edgeless={mode === 'edgeless'}
data-is-page-list={props.currentPage === null}
>
<div className={styles.headerLeftSide}>
{!open && <SidebarSwitch />}
{props.leftSlot}
<div>{!open && <SidebarSwitch />}</div>
<div
className={clsx(styles.headerLeftSideItem, {
[styles.headerLeftSideOpen]: open,
})}
>
{props.leftSlot}
</div>
</div>
{props.children}
<div className={styles.headerRightSide}>
<div
className={clsx(styles.headerRightSide, {
[styles.headerRightSideWindow]: isWindowsDesktop,
})}
>
<PluginHeader />
{useMemo(() => {
return Object.entries(HeaderRightItems).map(
@@ -227,6 +232,7 @@ export const Header = forwardRef<
);
}, [props])}
</div>
{isWindowsDesktop ? <WindowsAppControls /> : null}
</div>
</div>
);

View File

@@ -65,7 +65,7 @@ export const BlockSuiteEditorHeader: FC<
}}
/>
</div>
<div>
<div className={styles.pageTitle}>
{isEditable ? (
<div>
<input
@@ -88,11 +88,7 @@ export const BlockSuiteEditorHeader: FC<
</Button>
</div>
) : (
<span
data-testid="title-edit-button"
onClick={handleClick}
style={{ cursor: 'pointer' }}
>
<span data-testid="title-edit-button" onClick={handleClick}>
{title || 'Untitled'}
</span>
)}

View File

@@ -1,5 +1,7 @@
import type { ComplexStyleRule } from '@vanilla-extract/css';
import { style } from '@vanilla-extract/css';
import { createContainer, style } from '@vanilla-extract/css';
export const headerVanillaContainer = createContainer();
export const headerContainer = style({
height: 'auto',
@@ -27,35 +29,45 @@ export const headerContainer = style({
} as ComplexStyleRule);
export const header = style({
containerName: headerVanillaContainer,
containerType: 'inline-size',
flexShrink: 0,
height: '52px',
minHeight: '52px',
width: '100%',
padding: '0 20px',
display: 'flex',
justifyContent: 'space-between',
padding: '8px 20px',
display: 'grid',
gridTemplateColumns: '1fr auto 1fr',
alignItems: 'center',
background: 'var(--affine-background-primary-color)',
zIndex: 99,
position: 'relative',
selectors: {
'&[data-is-edgeless="true"]': {
'&[data-is-page-list="true"], &[data-is-edgeless="true"]': {
borderBottom: `1px solid var(--affine-border-color)`,
},
},
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
alignItems: 'start',
},
},
});
export const titleContainer = style({
width: '100%',
height: '100%',
margin: 'auto',
position: 'absolute',
inset: 'auto auto auto 50%',
transform: 'translate(-50%, 0px)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
alignContent: 'unset',
fontSize: 'var(--affine-font-base)',
['WebkitAppRegion' as string]: 'no-drag',
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
alignItems: 'start',
paddingTop: '2px',
},
},
});
export const title = style({
@@ -75,9 +87,26 @@ export const title = style({
},
},
} as ComplexStyleRule);
export const pageTitle = style({
maxWidth: '600px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
transition: 'width .15s',
cursor: 'pointer',
'@container': {
[`${headerVanillaContainer} (max-width: 1920px)`]: {
maxWidth: '800px',
},
[`${headerVanillaContainer} (max-width: 1300px)`]: {
maxWidth: '400px',
},
[`${headerVanillaContainer} (max-width: 768px)`]: {
maxWidth: '220px',
},
},
});
export const titleWrapper = style({
height: '100%',
position: 'relative',
display: 'flex',
justifyContent: 'center',
@@ -86,10 +115,28 @@ export const titleWrapper = style({
export const headerLeftSide = style({
display: 'flex',
alignItems: 'center',
width: '150px',
'@media': {
'(max-width: 900px)': {
width: 'auto',
transition: 'all .15s',
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
flexDirection: 'column',
alignItems: 'flex-start',
height: '68px',
},
},
});
export const headerLeftSideItem = style({
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
position: 'absolute',
left: '0',
bottom: '8px',
},
},
});
export const headerLeftSideOpen = style({
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
marginLeft: '20px',
},
},
});
@@ -99,7 +146,21 @@ export const headerRightSide = style({
alignItems: 'center',
gap: '12px',
zIndex: 1,
marginLeft: '20px',
justifyContent: 'flex-end',
transition: 'all .15s',
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
position: 'absolute',
height: 'auto',
right: '0',
bottom: '8px',
marginRight: '18px',
},
},
});
export const headerRightSideWindow = style({
marginRight: '140px',
});
export const browserWarning = style({
@@ -131,22 +192,12 @@ export const closeButton = style({
});
export const switchWrapper = style({
position: 'absolute',
right: '100%',
top: 0,
bottom: 0,
margin: 'auto',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
});
export const searchArrowWrapper = style({
position: 'absolute',
left: 'calc(100% + 4px)',
top: 0,
bottom: 0,
margin: 'auto',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
@@ -164,16 +215,13 @@ export const allPageListTitleWrapper = style({
color: 'var(--affine-text-primary-color)',
display: 'flex',
alignItems: 'center',
'::after': {
content: '""',
display: 'block',
width: '100%',
height: '1px',
background: 'var(--affine-border-color)',
position: 'absolute',
bottom: 0,
left: 0,
margin: '0 1px',
width: '100%',
height: '100%',
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
alignItems: 'flex-start',
marginTop: '8px',
},
},
});
export const pageListTitleIcon = style({
@@ -220,30 +268,36 @@ export const windowAppControlsWrapper = style({
gap: '2px',
transform: 'translateX(8px)',
height: '100%',
position: 'absolute',
right: '14px',
});
export const windowAppControl = style({
WebkitAppRegion: 'no-drag',
cursor: 'pointer',
display: 'inline-flex',
width: '42px',
height: 'calc(100% - 10px)',
paddingTop: '10px',
width: '51px',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '0',
selectors: {
'&[data-type="close"]': {
width: '56px',
paddingRight: '14px',
marginRight: '-14px',
paddingRight: '5px',
marginRight: '-12px',
},
'&[data-type="close"]:hover': {
background: 'var(--affine-error-color)',
color: '#FFFFFF',
background: 'var(--affine-windows-close-button)',
color: 'var(--affine-pure-white)',
},
'&:hover': {
background: 'var(--affine-background-tertiary-color)',
background: 'var(--affine-hover-color)',
},
},
'@container': {
[`${headerVanillaContainer} (max-width: 900px)`]: {
height: '50px',
paddingTop: '0',
},
},
} as ComplexStyleRule);

View File

@@ -1,6 +1,7 @@
import { Button, displayFlex, styled } from '@affine/component';
import { displayFlex, styled } from '@affine/component';
import { WorkspaceSubPath } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { Button } from '@toeverything/components/button';
import type { ReactElement } from 'react';
import { useNavigateHelper } from '../hooks/use-navigate-helper';

View File

@@ -1,22 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsxImportSource": "@emotion/react",
"incremental": true,
"experimentalDecorators": true,
"types": ["webpack-env", "ses"]
"outDir": "lib",
"typeRoots": ["../../node_modules", "../../node_modules/@types"],
"types": ["webpack-env", "ses", "affine__env"]
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"],

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/docs",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"type": "module",
"private": true,
"scripts": {
@@ -10,18 +10,18 @@
},
"dependencies": {
"@affine/component": "workspace:*",
"@blocksuite/block-std": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/block-std": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"express": "^4.18.2",
"jotai": "^2.2.2",
"react": "18.3.0-canary-1fdacbefd-20230630",
"react-dom": "18.3.0-canary-1fdacbefd-20230630",
"react-server-dom-webpack": "18.3.0-canary-1fdacbefd-20230630",
"waku": "0.12.1"
"waku": "0.14.0"
},
"devDependencies": {
"@types/react": "^18.2.17",

View File

@@ -4,7 +4,7 @@ export default defineRouter(
async id => {
switch (id) {
case 'index': {
const { default: AppCreator } = await import('./src/app.js');
const { default: AppCreator } = await import('./app.js');
return AppCreator(id);
}
default:

View File

@@ -29,7 +29,7 @@
<div class="spinner"></div>
</div>
<!--/placeholder1-->
<script src="./src/index.tsx" defer type="module"></script>
<script src="./index.tsx" defer type="module"></script>
<!--placeholder2-->
<!--/placeholder2-->
</body>

Binary file not shown.

View File

@@ -10,7 +10,8 @@
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"jsx": "react-jsx"
"jsx": "react-jsx",
"jsxImportSource": "react"
},
"include": ["src", "entries.ts"],
"references": [

View File

@@ -27,8 +27,8 @@ if (platform() === 'darwin') {
delay: 100,
});
await page.waitForSelector('v-line');
await page.focus('.affine-default-page-block-title');
await page.type('.affine-default-page-block-title', 'test1', {
await page.focus('.affine-doc-page-block-title');
await page.type('.affine-doc-page-block-title', 'test1', {
delay: 100,
});
await page.waitForTimeout(500);
@@ -36,8 +36,8 @@ if (platform() === 'darwin') {
delay: 100,
});
await page.waitForSelector('v-line');
await page.focus('.affine-default-page-block-title');
await page.type('.affine-default-page-block-title', 'test2', {
await page.focus('.affine-doc-page-block-title');
await page.type('.affine-doc-page-block-title', 'test2', {
delay: 100,
});
await page.waitForTimeout(500);
@@ -45,14 +45,14 @@ if (platform() === 'darwin') {
delay: 100,
});
await page.waitForSelector('v-line');
await page.focus('.affine-default-page-block-title');
await page.type('.affine-default-page-block-title', 'test3', {
await page.focus('.affine-doc-page-block-title');
await page.type('.affine-doc-page-block-title', 'test3', {
delay: 100,
});
}
{
const title = (await page
.locator('.affine-default-page-block-title')
.locator('.affine-doc-page-block-title')
.textContent()) as string;
expect(title.trim()).toBe('test3');
}
@@ -63,7 +63,7 @@ if (platform() === 'darwin') {
await page.waitForTimeout(1000);
{
const title = (await page
.locator('.affine-default-page-block-title')
.locator('.affine-doc-page-block-title')
.textContent()) as string;
expect(title.trim()).toBe('test1');
}
@@ -73,7 +73,7 @@ if (platform() === 'darwin') {
await page.waitForTimeout(1000);
{
const title = (await page
.locator('.affine-default-page-block-title')
.locator('.affine-doc-page-block-title')
.textContent()) as string;
expect(title.trim()).toBe('test3');
}

View File

@@ -29,7 +29,6 @@ test.skip('move workspace db file', async ({ page, appInfo, workspace }) => {
// move db file to tmp folder
await page.evaluate(tmpPath => {
// @ts-expect-error
window.apis?.dialog.setFakeDialogResult({
filePath: tmpPath,
});
@@ -47,8 +46,8 @@ test.skip('move workspace db file', async ({ page, appInfo, workspace }) => {
test('export then add', async ({ page, appInfo, workspace }) => {
const w = await workspace.current();
await page.focus('.affine-default-page-block-title');
await page.fill('.affine-default-page-block-title', 'test1');
await page.focus('.affine-doc-page-block-title');
await page.fill('.affine-doc-page-block-title', 'test1');
await page.getByTestId('slider-bar-workspace-setting-button').click();
await expect(page.getByTestId('setting-modal')).toBeVisible();
@@ -72,7 +71,6 @@ test('export then add', async ({ page, appInfo, workspace }) => {
// export db file to tmp folder
await page.evaluate(tmpPath => {
// @ts-expect-error
window.apis?.dialog.setFakeDialogResult({
filePath: tmpPath,
});
@@ -92,7 +90,6 @@ test('export then add', async ({ page, appInfo, workspace }) => {
await page.getByTestId('add-or-new-workspace').click();
await page.evaluate(tmpPath => {
// @ts-expect-error
window.apis?.dialog.setFakeDialogResult({
filePath: tmpPath,
});

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/electron",
"private": true,
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"author": "affine",
"repository": {
"url": "https://github.com/toeverything/AFFiNE",
@@ -28,10 +28,10 @@
"@affine/env": "workspace:*",
"@affine/native": "workspace:*",
"@affine/sdk": "workspace:*",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"@electron-forge/cli": "^6.2.1",
"@electron-forge/core": "^6.2.1",
"@electron-forge/core-utils": "^6.2.1",

View File

@@ -115,7 +115,11 @@ function startPollingSecondaryDB(db: WorkspaceSQLiteDB) {
const secondaryDB = new SecondaryWorkspaceSQLiteDB(path, db);
return new Observable<SecondaryWorkspaceSQLiteDB>(subscriber => {
subscriber.next(secondaryDB);
return () => secondaryDB.destroy();
return () => {
secondaryDB.destroy().catch(err => {
subscriber.error(err);
});
};
});
}),
switchMap(secondaryDB => {

View File

@@ -1,6 +1,13 @@
import path from 'node:path';
import { ValidationResult } from '@affine/native';
import type {
FakeDialogResult,
LoadDBFileResult,
MoveDBFileResult,
SaveDBFileResult,
SelectDBFileLocationResult,
} from '@toeverything/infra/type';
import fs from 'fs-extra';
import { nanoid } from 'nanoid';
@@ -28,13 +35,6 @@ export async function revealDBFile(workspaceId: string) {
await mainRPC.showItemInFolder(meta.secondaryDBPath ?? meta.mainDBPath);
}
// provide a backdoor to set dialog path for testing in playwright
export interface FakeDialogResult {
canceled?: boolean;
filePath?: string;
filePaths?: string[];
}
// result will be used in the next call to showOpenDialog
// if it is being read once, it will be reset to undefined
let fakeDialogResult: FakeDialogResult | undefined = undefined;
@@ -53,23 +53,6 @@ export function setFakeDialogResult(result: FakeDialogResult | undefined) {
}
}
const ErrorMessages = [
'DB_FILE_ALREADY_LOADED',
'DB_FILE_PATH_INVALID',
'DB_FILE_INVALID',
'DB_FILE_MIGRATION_FAILED',
'FILE_ALREADY_EXISTS',
'UNKNOWN_ERROR',
] as const;
type ErrorMessage = (typeof ErrorMessages)[number];
export interface SaveDBFileResult {
filePath?: string;
canceled?: boolean;
error?: ErrorMessage;
}
const extension = 'affine';
function getDefaultDBFileName(name: string, id: string) {
@@ -125,12 +108,6 @@ export async function saveDBFileAs(
}
}
export interface SelectDBFileLocationResult {
filePath?: string;
error?: ErrorMessage;
canceled?: boolean;
}
export async function selectDBFileLocation(): Promise<SelectDBFileLocationResult> {
try {
const ret =
@@ -157,12 +134,6 @@ export async function selectDBFileLocation(): Promise<SelectDBFileLocationResult
}
}
export interface LoadDBFileResult {
workspaceId?: string;
error?: ErrorMessage;
canceled?: boolean;
}
/**
* This function is called when the user clicks the "Load" button in the "Load Workspace" dialog.
*
@@ -255,12 +226,6 @@ export async function loadDBFile(): Promise<LoadDBFileResult> {
}
}
export interface MoveDBFileResult {
filePath?: string;
error?: ErrorMessage;
canceled?: boolean;
}
/**
* This function is called when the user clicks the "Move" button in the "Move Workspace Storage" setting.
*

View File

@@ -38,7 +38,7 @@ app.on('second-instance', () => {
);
});
app.on('open-url', async (_, _url) => {
app.on('open-url', (_, _url) => {
// todo: handle `affine://...` urls
});
@@ -54,7 +54,11 @@ app.on('window-all-closed', () => {
/**
* @see https://www.electronjs.org/docs/v14-x-y/api/app#event-activate-macos Event: 'activate'
*/
app.on('activate', restoreOrCreateWindow);
app.on('activate', () => {
restoreOrCreateWindow().catch(err => {
console.error(err);
});
});
/**
* Create app window when background process will be ready

View File

@@ -34,7 +34,7 @@ export function getGoogleOauthCode() {
logger.error('Failed to open external url', e);
reject(e);
});
const handleOpenUrl = async (_: any, url: string) => {
const handleOpenUrl = (_: any, url: string) => {
const mainWindow = BrowserWindow.getAllWindows().find(
w => !w.isDestroyed()
);

View File

@@ -99,7 +99,9 @@ export const registerUpdater = async () => {
});
autoUpdater.forceDevUpdateConfig = isDev;
app.on('activate', async () => {
await checkForUpdates(false);
app.on('activate', () => {
checkForUpdates(false).catch(err => {
console.error(err);
});
});
};

View File

@@ -19,10 +19,15 @@ const mainThread = AsyncCall<{
channel: new MessageEventChannel(parentPort),
});
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.log = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.error = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.info = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.debug = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.warn = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-var-requires

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/server",
"private": true,
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"description": "Affine Node.js server",
"type": "module",
"bin": {

View File

@@ -77,7 +77,7 @@ export class WorkspaceResolver {
return workspace.permission;
}
const permission = this.permissionProvider.get(workspace.id, user.id);
const permission = await this.permissionProvider.get(workspace.id, user.id);
if (!permission) {
throw new ForbiddenException();

View File

@@ -9,8 +9,10 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
}
async enableShutdownHooks(app: INestApplication) {
process.on('beforeExit', async () => {
await app.close();
process.on('beforeExit', () => {
app.close().catch(e => {
console.error(e);
});
});
}
}

View File

@@ -30,13 +30,13 @@
"wait-on": "^7.0.1"
},
"devDependencies": {
"@blocksuite/block-std": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/block-std": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/icons": "^2.1.29",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"react": "18.2.0",
"react-dom": "18.2.0"
},
@@ -48,5 +48,5 @@
"@blocksuite/lit": "*",
"@blocksuite/store": "*"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -6,14 +6,19 @@ import { rootBlockHubAtom } from '@affine/workspace/atom';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import type { EditorContainer } from '@blocksuite/editor';
import type { Page } from '@blocksuite/store';
import { createMemoryStorage, Workspace } from '@blocksuite/store';
import { createMemoryStorage, Schema, Workspace } from '@blocksuite/store';
import { expect } from '@storybook/jest';
import type { Meta, StoryFn } from '@storybook/react';
import { use } from 'foxact/use';
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
const blockSuiteWorkspace = new Workspace({
id: 'test',
blobStorages: [createMemoryStorage],
schema,
});
async function initPage(page: Page) {
@@ -34,7 +39,6 @@ async function initPage(page: Page) {
page.resetHistory();
}
blockSuiteWorkspace.register(AffineSchemas).register(__unstableSchemas);
const page = blockSuiteWorkspace.createPage('page0');
type BlockSuiteMeta = Meta<typeof BlockSuiteEditor>;

View File

@@ -1,6 +1,7 @@
import type { WorkspaceAvatarProps } from '@affine/component/workspace-avatar';
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
import { Workspace } from '@blocksuite/store';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { Schema, Workspace } from '@blocksuite/store';
import type { Meta, StoryFn } from '@storybook/react';
export default {
@@ -17,8 +18,13 @@ export default {
},
} satisfies Meta<WorkspaceAvatarProps>;
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
const basicBlockSuiteWorkspace = new Workspace({
id: 'blocksuite-local',
schema,
});
basicBlockSuiteWorkspace.meta.setName('Hello World');
@@ -33,6 +39,7 @@ Basic.args = {
const avatarBlockSuiteWorkspace = new Workspace({
id: 'blocksuite-local',
schema,
});
avatarBlockSuiteWorkspace.meta.setName('Hello World');

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/monorepo",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"private": true,
"author": "toeverything",
"license": "MPL-2.0",
@@ -9,6 +9,7 @@
"apps/*",
"plugins/*",
"packages/*",
"packages/@types/*",
"tests/fixtures",
"tests/kit",
"tests/affine-legacy/*",

54
packages/@types/env/__all.d.ts vendored Normal file
View File

@@ -0,0 +1,54 @@
import type { Environment, Platform, RuntimeConfig } from '@affine/env/global';
import type {
DBHandlerManager,
DebugHandlerManager,
DialogHandlerManager,
ExportHandlerManager,
UIHandlerManager,
UnwrapManagerHandlerToClientSide,
UpdaterHandlerManager,
WorkspaceHandlerManager,
} from '@toeverything/infra';
declare global {
interface Window {
appInfo: {
electron: boolean;
};
apis: {
db: UnwrapManagerHandlerToClientSide<DBHandlerManager>;
debug: UnwrapManagerHandlerToClientSide<DebugHandlerManager>;
dialog: UnwrapManagerHandlerToClientSide<DialogHandlerManager>;
export: UnwrapManagerHandlerToClientSide<ExportHandlerManager>;
ui: UnwrapManagerHandlerToClientSide<UIHandlerManager>;
updater: UnwrapManagerHandlerToClientSide<UpdaterHandlerManager>;
workspace: UnwrapManagerHandlerToClientSide<WorkspaceHandlerManager>;
};
events: any;
}
interface WindowEventMap {
'migration-done': CustomEvent;
}
// eslint-disable-next-line no-var
var process: {
env: Record<string, string>;
};
// eslint-disable-next-line no-var
var $migrationDone: boolean;
// eslint-disable-next-line no-var
var platform: Platform | undefined;
// eslint-disable-next-line no-var
var environment: Environment;
// eslint-disable-next-line no-var
var runtimeConfig: RuntimeConfig;
// eslint-disable-next-line no-var
var $AFFINE_SETUP: boolean | undefined;
// eslint-disable-next-line no-var
var editorVersion: string | undefined;
// eslint-disable-next-line no-var
var prefixUrl: string;
// eslint-disable-next-line no-var
var websocketPrefixUrl: string;
}

11
packages/@types/env/package.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "@types/affine__env",
"private": true,
"types": "./__all.d.ts",
"type": "module",
"dependencies": {
"@affine/env": "workspace:*",
"@toeverything/infra": "workspace:*"
},
"version": "0.8.0-canary.11"
}

View File

@@ -20,5 +20,5 @@
"peerDependencies": {
"ts-node": "*"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -51,12 +51,12 @@
"rxjs": "^7.8.1"
},
"devDependencies": {
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/icons": "^2.1.29",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"@types/react": "^18.2.17",
"@types/react-datepicker": "^4.15.0",
"@types/react-dnd": "^3.0.2",
@@ -66,5 +66,5 @@
"vite": "^4.4.7",
"yjs": "^13.6.7"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -17,23 +17,18 @@ export const navWrapperStyle = style({
paddingBottom: '8px',
backgroundColor: 'transparent',
'@media': {
[`(max-width: ${floatingMaxWidth}px)`]: {
position: 'absolute',
width: `calc(${navWidthVar})`,
zIndex: 4,
backgroundColor: 'var(--affine-background-primary-color)',
selectors: {
'&[data-open="false"]': {
marginLeft: `calc((10vw + ${navWidthVar}) * -1)`,
},
},
},
print: {
display: 'none',
zIndex: -1,
},
},
selectors: {
'&[data-is-floating="true"]': {
position: 'absolute',
width: `calc(${navWidthVar})`,
zIndex: 4,
backgroundColor: 'var(--affine-background-primary-color)',
},
'&[data-open="false"]': {
marginLeft: `calc(${navWidthVar} * -1)`,
},
@@ -93,17 +88,15 @@ export const sidebarFloatMaskStyle = style({
right: '100%',
bottom: 0,
background: 'var(--affine-background-modal-color)',
'@media': {
[`(max-width: ${floatingMaxWidth}px)`]: {
selectors: {
'&[data-open="true"]': {
opacity: 1,
pointerEvents: 'auto',
right: '0',
zIndex: 3,
},
},
selectors: {
'&[data-open="true"][data-is-floating="true"]': {
opacity: 1,
pointerEvents: 'auto',
right: '0',
zIndex: 3,
},
},
'@media': {
print: {
display: 'none',
},

View File

@@ -59,18 +59,22 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
useEffect(() => {
function onResize() {
const { matches } = window.matchMedia(
const isFloatingMaxWidth = window.matchMedia(
`(max-width: ${floatingMaxWidth}px)`
);
).matches;
const isOverflowWidth = window.matchMedia(
`(max-width: ${appSidebarWidth / 0.4}px)`
).matches;
const isFloating = isFloatingMaxWidth || isOverflowWidth;
if (
open === undefined &&
localStorage.getItem(APP_SIDEBAR_OPEN) === null
) {
// give the initial value,
// so that the sidebar can be closed on mobile by default
setOpen(!matches);
setOpen(!isFloating);
}
setAppSidebarFloating(matches && !!open);
setAppSidebarFloating(isFloating && !!open);
}
onResize();
@@ -78,7 +82,7 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
return () => {
window.removeEventListener('resize', onResize);
};
}, [open, setAppSidebarFloating, setOpen]);
}, [appSidebarWidth, open, setAppSidebarFloating, setOpen]);
// disable animation to avoid UI flash
const enableAnimation = useEnableAnimation();
@@ -99,6 +103,7 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
})}
data-open={open}
data-is-macos-electron={isMacosDesktop}
data-is-floating={appSidebarFloating}
data-enable-animation={enableAnimation && !isResizing}
>
<nav className={navStyle} ref={navRef} data-testid="app-sidebar">

View File

@@ -10,7 +10,6 @@ import {
} from '@blocksuite/icons';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import { useStaticBlockSuiteWorkspace } from '@toeverything/infra/__internal__/react';
import type { FC } from 'react';
import { useCallback } from 'react';
import { WorkspaceAvatar } from '../../workspace-avatar';
@@ -21,9 +20,6 @@ import {
StyleWorkspaceTitle,
} from './styles';
export type WorkspaceTypeProps = {
flavour: WorkspaceFlavour;
};
const JoinedWorkspaceIcon = () => {
return <DefaultJoinedWorkspaceIcon style={{ color: '#FF646B' }} />;
};
@@ -39,7 +35,11 @@ const LocalDataIcon = () => {
return <DefaultLocalDataIcon style={{ color: '#62CD80' }} />;
};
const WorkspaceType: FC<WorkspaceTypeProps> = ({ flavour }) => {
export interface WorkspaceTypeProps {
flavour: WorkspaceFlavour;
}
const WorkspaceType = ({ flavour }: WorkspaceTypeProps) => {
const t = useAFFiNEI18N();
// fixme: cloud regression
const isOwner = true;
@@ -66,19 +66,19 @@ const WorkspaceType: FC<WorkspaceTypeProps> = ({ flavour }) => {
);
};
export type WorkspaceCardProps = {
export interface WorkspaceCardProps {
currentWorkspaceId: string | null;
meta: RootWorkspaceMetadata;
onClick: (workspaceId: string) => void;
onSettingClick: (workspaceId: string) => void;
};
}
export const WorkspaceCard: FC<WorkspaceCardProps> = ({
export const WorkspaceCard = ({
onClick,
onSettingClick,
currentWorkspaceId,
meta,
}) => {
}: WorkspaceCardProps) => {
const t = useAFFiNEI18N();
const workspace = useStaticBlockSuiteWorkspace(meta.id);
const [name] = useBlockSuiteWorkspaceName(workspace);

View File

@@ -1,10 +1,9 @@
import { lottieAtom } from '@affine/jotai';
import { useAtomValue } from 'jotai';
import type { AnimationItem } from 'lottie-web';
import type { FC } from 'react';
import { useEffect, useRef } from 'react';
type CustomLottieProps = {
interface CustomLottieProps {
options: {
loop?: boolean | number | undefined;
autoReverse?: boolean | undefined;
@@ -18,15 +17,15 @@ type CustomLottieProps = {
speed?: number | undefined;
width?: number | string | undefined;
height?: number | string | undefined;
};
}
export const InternalLottie: FC<CustomLottieProps> = ({
export const InternalLottie = ({
options,
isStopped,
speed,
width,
height,
}) => {
}: CustomLottieProps) => {
const element = useRef<HTMLDivElement>(null);
const lottieInstance = useRef<AnimationItem>();
const lottie = useAtomValue(lottieAtom);

View File

@@ -181,7 +181,9 @@ function NotificationCard(props: NotificationCardProps): ReactElement {
const onClickUndo = useCallback(() => {
if (notification.undo) {
return notification.undo();
notification.undo().catch(err => {
console.error(err);
});
}
return void 0;
}, [notification]);

View File

@@ -28,6 +28,17 @@ import type { ListData, PageListProps, TrashListData } from './type';
import { useSorter } from './use-sorter';
import { formatDate, useIsSmallDevices } from './utils';
interface AllPagesHeadProps {
isPublicWorkspace: boolean;
sorter: ReturnType<typeof useSorter<ListData>>;
createNewPage: () => void;
createNewEdgeless: () => void;
importFile: () => void;
getPageInfo: GetPageInfoById;
propertiesMeta: PropertiesMeta;
workspaceId: string;
}
const AllPagesHead = ({
isPublicWorkspace,
sorter,
@@ -37,16 +48,7 @@ const AllPagesHead = ({
getPageInfo,
propertiesMeta,
workspaceId,
}: {
isPublicWorkspace: boolean;
sorter: ReturnType<typeof useSorter<ListData>>;
createNewPage: () => void;
createNewEdgeless: () => void;
importFile: () => void;
getPageInfo: GetPageInfoById;
propertiesMeta: PropertiesMeta;
workspaceId: string;
}) => {
}: AllPagesHeadProps) => {
const t = useAFFiNEI18N();
const titleList = useMemo(
() => [
@@ -235,10 +237,15 @@ const TrashListHead = () => {
);
};
export const PageListTrashView: React.FC<{
interface PageListTrashViewProps {
list: TrashListData[];
fallback?: React.ReactNode;
}> = ({ list, fallback }) => {
}
export const PageListTrashView = ({
list,
fallback,
}: PageListTrashViewProps) => {
const t = useAFFiNEI18N();
const theme = useTheme();

View File

@@ -8,7 +8,6 @@ import {
OpenInNewIcon,
ResetIcon,
} from '@blocksuite/icons';
import type React from 'react';
import { useState } from 'react';
import {
@@ -21,7 +20,7 @@ import {
} from '../../..';
import { DisablePublicSharing, MoveToTrash } from './operation-menu-items';
export type OperationCellProps = {
export interface OperationCellProps {
title: string;
favorite: boolean;
isPublic: boolean;
@@ -29,9 +28,9 @@ export type OperationCellProps = {
onToggleFavoritePage: () => void;
onRemoveToTrash: () => void;
onDisablePublicSharing: () => void;
};
}
export const OperationCell: React.FC<OperationCellProps> = ({
export const OperationCell = ({
title,
favorite,
isPublic,
@@ -39,7 +38,7 @@ export const OperationCell: React.FC<OperationCellProps> = ({
onToggleFavoritePage,
onRemoveToTrash,
onDisablePublicSharing,
}) => {
}: OperationCellProps) => {
const t = useAFFiNEI18N();
const [open, setOpen] = useState(false);
const [openDisableShared, setOpenDisableShared] = useState(false);
@@ -118,16 +117,16 @@ export const OperationCell: React.FC<OperationCellProps> = ({
);
};
export type TrashOperationCellProps = {
export interface TrashOperationCellProps {
onPermanentlyDeletePage: () => void;
onRestorePage: () => void;
onOpenPage: () => void;
};
}
export const TrashOperationCell: React.FC<TrashOperationCellProps> = ({
export const TrashOperationCell = ({
onPermanentlyDeletePage,
onRestorePage,
}) => {
}: TrashOperationCellProps) => {
const t = useAFFiNEI18N();
const [open, setOpen] = useState(false);
return (

View File

@@ -1,7 +1,7 @@
import type { Collection, Filter, VariableMap } from '@affine/env/filter';
import type { DBSchema } from 'idb';
import type { IDBPDatabase } from 'idb';
import { openDB } from 'idb';
import type { IDBPDatabase } from 'idb/build/entry';
import { useAtom } from 'jotai';
import { atomWithReset, RESET } from 'jotai/utils';
import { useCallback } from 'react';

View File

@@ -63,10 +63,14 @@ export const CollectionBar = (props: CollectionBarProps) => {
: t['com.affine.collection-bar.action.tooltip.pin'](),
className: styles.pin,
click: () => {
return setting.updateCollection({
...collection,
pinned: !collection.pinned,
});
setting
.updateCollection({
...collection,
pinned: !collection.pinned,
})
.catch(err => {
console.error(err);
});
},
},
{
@@ -102,6 +106,7 @@ export const CollectionBar = (props: CollectionBarProps) => {
init={collection}
open={open}
onClose={onClose}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onConfirm={setting.updateCollection}
></EditCollectionModel>
<ViewLayersIcon

View File

@@ -21,7 +21,7 @@ export const viewButton = style({
fontSize: 'var(--affine-font-xs)',
background: 'var(--affine-white)',
['WebkitAppRegion' as string]: 'no-drag',
maxWidth: '200px',
maxWidth: '150px',
color: 'var(--affine-text-secondary-color)',
border: '1px solid var(--affine-border-color)',
transition: 'margin-left 0.2s ease-in-out',
@@ -30,15 +30,6 @@ export const viewButton = style({
background: 'var(--affine-hover-color)',
},
marginRight: '20px',
'@media': {
'(max-width: 1200px)': {
maxWidth: '100px',
},
'(max-width: 900px)': {
maxWidth: '150px',
marginRight: '10px',
},
},
});
globalStyle(`${viewButton} > span`, {
display: 'block',
@@ -74,6 +65,8 @@ export const deleteOption = style({
export const filterButton = style({
borderRadius: '8px',
height: '100%',
width: '100%',
marginRight: '20px',
padding: '4px 8px',
fontSize: 'var(--affine-font-xs)',
background: 'var(--affine-white)',

View File

@@ -43,10 +43,14 @@ const CollectionOption = ({
icon: <PinIcon />,
name: 'pin',
click: () => {
return setting.updateCollection({
...collection,
pinned: !collection.pinned,
});
setting
.updateCollection({
...collection,
pinned: !collection.pinned,
})
.catch(err => {
console.error(err);
});
},
},
{
@@ -144,10 +148,14 @@ export const CollectionList = ({
const [collection, setCollection] = useState<Collection>();
const onChange = useCallback(
(filterList: Filter[]) => {
return setting.updateCollection({
...setting.currentCollection,
filterList,
});
setting
.updateCollection({
...setting.currentCollection,
filterList,
})
.catch(err => {
console.error(err);
});
},
[setting]
);
@@ -156,10 +164,9 @@ export const CollectionList = ({
[]
);
const onConfirm = useCallback(
(view: Collection) => {
return setting.updateCollection(view).then(() => {
closeUpdateCollectionModal();
});
async (view: Collection) => {
await setting.updateCollection(view);
closeUpdateCollectionModal();
},
[closeUpdateCollectionModal, setting]
);

View File

@@ -32,7 +32,7 @@ type CreateCollectionProps = {
};
type SaveCollectionButtonProps = {
onConfirm: (collection: Collection) => void;
onConfirm: (collection: Collection) => Promise<void>;
getPageInfo: GetPageInfoById;
propertiesMeta: PropertiesMeta;
filterList: Filter[];
@@ -49,7 +49,7 @@ export const EditCollectionModel = ({
title,
}: {
init?: Collection;
onConfirm: (view: Collection) => void;
onConfirm: (view: Collection) => Promise<void>;
open: boolean;
onClose: () => void;
title?: string;
@@ -57,6 +57,18 @@ export const EditCollectionModel = ({
propertiesMeta: PropertiesMeta;
}) => {
const t = useAFFiNEI18N();
const onConfirmOnCollection = useCallback(
(view: Collection) => {
onConfirm(view)
.then(() => {
onClose();
})
.catch(err => {
console.error(err);
});
},
[onClose, onConfirm]
);
return (
<Modal open={open} onClose={onClose}>
<ModalWrapper
@@ -75,10 +87,7 @@ export const EditCollectionModel = ({
init={init}
getPageInfo={getPageInfo}
onCancel={onClose}
onConfirm={view => {
onConfirm(view);
onClose();
}}
onConfirm={onConfirmOnCollection}
/>
) : null}
</ModalWrapper>

View File

@@ -10,7 +10,7 @@ import { ProviderComposer } from '..';
test('ProviderComposer', async () => {
const Context = createContext('null');
const Provider: React.FC<React.PropsWithChildren> = ({ children }) => {
const Provider = ({ children }: React.PropsWithChildren) => {
return <Context.Provider value="test1">{children}</Context.Provider>;
};
const ConsumerComponent = () => {

View File

@@ -1,11 +1,15 @@
import type { FC, PropsWithChildren, ReactNode } from 'react';
import type { ReactNode } from 'react';
import { cloneElement } from 'react';
export const ProviderComposer: FC<
PropsWithChildren<{
contexts: any;
}>
> = ({ contexts, children }) =>
interface ProviderComposerProps {
contexts: any;
children: ReactNode;
}
export const ProviderComposer = ({
contexts,
children,
}: ProviderComposerProps) =>
contexts.reduceRight(
(kids: ReactNode, parent: any) =>
cloneElement(parent, {

View File

@@ -1,17 +1,17 @@
import { Modal, ModalCloseButton, ModalWrapper } from '@affine/component';
import type { FC, PropsWithChildren } from 'react';
import type { PropsWithChildren } from 'react';
import { useCallback } from 'react';
export type SettingModalProps = {
export interface SettingModalProps {
open: boolean;
setOpen: (value: boolean) => void;
};
}
export const SettingModal: FC<PropsWithChildren<SettingModalProps>> = ({
export const SettingModal = ({
children,
open,
setOpen,
}) => {
}: PropsWithChildren<SettingModalProps>) => {
const handleClose = useCallback(() => {
setOpen(false);
}, [setOpen]);

View File

@@ -1,13 +1,18 @@
import type { FC, HTMLAttributes, ReactNode } from 'react';
import type { HTMLAttributes, ReactNode } from 'react';
import { settingHeader } from './share.css';
export const SettingHeader: FC<
{ title: ReactNode; subtitle?: ReactNode } & Omit<
HTMLAttributes<HTMLDivElement>,
'title'
>
> = ({ title, subtitle, ...otherProps }) => {
interface SettingHeaderProps
extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
title: ReactNode;
subtitle?: ReactNode;
}
export const SettingHeader = ({
title,
subtitle,
...otherProps
}: SettingHeaderProps) => {
return (
<div className={settingHeader} {...otherProps}>
<div className="title">{title}</div>

View File

@@ -1,18 +1,18 @@
import clsx from 'clsx';
import type { CSSProperties, FC, PropsWithChildren, ReactNode } from 'react';
import type { CSSProperties, PropsWithChildren, ReactNode } from 'react';
import { settingRow } from './share.css';
export const SettingRow: FC<
PropsWithChildren<{
name: ReactNode;
desc: ReactNode;
style?: CSSProperties;
onClick?: () => void;
spreadCol?: boolean;
testId?: string;
}>
> = ({
interface SettingRowProps {
name: ReactNode;
desc: ReactNode;
style?: CSSProperties;
onClick?: () => void;
spreadCol?: boolean;
testId?: string;
}
export const SettingRow = ({
name,
desc,
children,
@@ -20,7 +20,7 @@ export const SettingRow: FC<
style,
spreadCol = true,
testId = '',
}) => {
}: PropsWithChildren<SettingRowProps>) => {
return (
<div
className={clsx(settingRow, {

View File

@@ -1,11 +1,15 @@
import type { FC, PropsWithChildren, ReactNode } from 'react';
import type { PropsWithChildren, ReactNode } from 'react';
import { wrapper } from './share.css';
export const SettingWrapper: FC<
PropsWithChildren<{
title?: ReactNode;
}>
> = ({ title, children }) => {
interface SettingWrapperProps {
title?: ReactNode;
}
export const SettingWrapper = ({
title,
children,
}: PropsWithChildren<SettingWrapperProps>) => {
return (
<div className={wrapper}>
{title ? <div className="title">{title}</div> : null}

View File

@@ -1,5 +1,4 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { FC } from 'react';
import {
ExportToHtmlMenuItem,
@@ -8,9 +7,9 @@ import {
ExportToPngMenuItem,
} from '../page-list/operation-menu-items/export';
import { actionsStyle, descriptionStyle, menuItemStyle } from './index.css';
import type { ShareMenuProps } from './share-menu';
// import type { ShareMenuProps } from './share-menu';
export const Export: FC<ShareMenuProps> = () => {
export const Export = () => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>

View File

@@ -5,8 +5,7 @@ import type {
import { ExportIcon, PublishIcon, ShareIcon } from '@blocksuite/icons';
import type { Page } from '@blocksuite/store';
import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public';
import type { FC } from 'react';
import { useRef } from 'react';
import { type ReactElement, useRef } from 'react';
import { useCallback, useState } from 'react';
import { Button } from '../../ui/button';
@@ -16,22 +15,27 @@ import { containerStyle, indicatorContainerStyle, tabStyle } from './index.css';
import { SharePage } from './share-page';
import { ShareWorkspace } from './share-workspace';
import { StyledIndicator, TabItem } from './styles';
type SharePanel = 'SharePage' | 'Export' | 'ShareWorkspace';
const MenuItems: Record<SharePanel, FC<ShareMenuProps>> = {
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 type ShareMenuProps<
export interface ShareMenuProps<
Workspace extends AffineCloudWorkspace | LocalWorkspace =
| AffineCloudWorkspace
| LocalWorkspace,
> = {
> {
workspace: Workspace;
currentPage: Page;
onEnableAffineCloud: (workspace: LocalWorkspace) => void;
@@ -41,7 +45,7 @@ export type ShareMenuProps<
workspace: Workspace,
publish: boolean
) => Promise<void>;
};
}
function assertInstanceOf<T, U extends T>(
obj: T,
@@ -52,7 +56,7 @@ function assertInstanceOf<T, U extends T>(
}
}
export const ShareMenu: FC<ShareMenuProps> = props => {
export const ShareMenu = (props: ShareMenuProps) => {
const [activeItem, setActiveItem] = useState<SharePanel>('SharePage');
const [isPublic] = useBlockSuiteWorkspacePageIsPublic(props.currentPage);
const [open, setOpen] = useState(false);
@@ -84,7 +88,7 @@ export const ShareMenu: FC<ShareMenuProps> = props => {
activeItem: SharePanel;
onChangeTab: (selectedItem: SharePanel) => void;
}
const ShareMenu: FC<ShareMenuProps> = ({ activeItem, onChangeTab }) => {
const ShareMenu = ({ activeItem, onChangeTab }: ShareMenuProps) => {
const handleButtonClick = (itemName: SharePanel) => {
onChangeTab(itemName);
setActiveItem(itemName);

View File

@@ -3,7 +3,6 @@ import { WorkspaceFlavour } from '@affine/env/workspace';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public';
import type { FC } from 'react';
import { useState } from 'react';
import { useCallback, useMemo } from 'react';
@@ -17,7 +16,7 @@ import {
import type { ShareMenuProps } from './share-menu';
import { StyledDisableButton, StyledInput, StyledLinkSpan } from './styles';
export const LocalSharePage: FC<ShareMenuProps> = props => {
export const LocalSharePage = (props: ShareMenuProps) => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
@@ -35,7 +34,7 @@ export const LocalSharePage: FC<ShareMenuProps> = props => {
);
};
export const AffineSharePage: FC<ShareMenuProps> = props => {
export const AffineSharePage = (props: ShareMenuProps) => {
const [isPublic, setIsPublic] = useBlockSuiteWorkspacePageIsPublic(
props.currentPage
);
@@ -47,9 +46,15 @@ export const AffineSharePage: FC<ShareMenuProps> = props => {
const onClickCreateLink = useCallback(() => {
setIsPublic(true);
}, [setIsPublic]);
const onClickCopyLink = useCallback(async () => {
await navigator.clipboard.writeText(sharingUrl);
toast(t['Copied link to clipboard']());
const onClickCopyLink = useCallback(() => {
navigator.clipboard
.writeText(sharingUrl)
.then(() => {
toast(t['Copied link to clipboard']());
})
.catch(err => {
console.error(err);
});
}, [sharingUrl, t]);
const onDisablePublic = useCallback(() => {
setIsPublic(false);
@@ -117,7 +122,7 @@ export const AffineSharePage: FC<ShareMenuProps> = props => {
);
};
export const SharePage: FC<ShareMenuProps> = props => {
export const SharePage = (props: ShareMenuProps) => {
if (props.workspace.flavour === WorkspaceFlavour.LOCAL) {
return <LocalSharePage {...props} />;
} else if (props.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD) {

View File

@@ -4,13 +4,12 @@ import type {
} from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { FC } from 'react';
import { Button } from '../../ui/button';
import { descriptionStyle, menuItemStyle } from './index.css';
import type { ShareMenuProps } from './share-menu';
const ShareLocalWorkspace: FC<ShareMenuProps<LocalWorkspace>> = props => {
const ShareLocalWorkspace = (props: ShareMenuProps<LocalWorkspace>) => {
const t = useAFFiNEI18N();
return (
<div className={menuItemStyle}>
@@ -29,9 +28,7 @@ const ShareLocalWorkspace: FC<ShareMenuProps<LocalWorkspace>> = props => {
);
};
const ShareAffineWorkspace: FC<
ShareMenuProps<AffineCloudWorkspace>
> = props => {
const ShareAffineWorkspace = (props: ShareMenuProps<AffineCloudWorkspace>) => {
// fixme: regression
const isPublicWorkspace = false;
const t = useAFFiNEI18N();
@@ -54,7 +51,7 @@ const ShareAffineWorkspace: FC<
);
};
export const ShareWorkspace: FC<ShareMenuProps> = props => {
export const ShareWorkspace = (props: ShareMenuProps) => {
if (props.workspace.flavour === WorkspaceFlavour.LOCAL) {
return (
<ShareLocalWorkspace {...(props as ShareMenuProps<LocalWorkspace>)} />

View File

@@ -1,7 +1,6 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ArrowLeftSmallIcon, ArrowRightSmallIcon } from '@blocksuite/icons';
import clsx from 'clsx';
import type { FC } from 'react';
import { useState } from 'react';
import { Modal, ModalCloseButton, ModalWrapper } from '../..';
@@ -26,12 +25,12 @@ import {
videoStyle,
} from './index.css';
type TourModalProps = {
export interface TourModalProps {
open: boolean;
onClose: () => void;
};
}
export const TourModal: FC<TourModalProps> = ({ open, onClose }) => {
export const TourModal = ({ open, onClose }: TourModalProps) => {
const t = useAFFiNEI18N();
const [step, setStep] = useState(-1);
const handleClose = () => {

View File

@@ -1,24 +1,24 @@
import * as Avatar from '@radix-ui/react-avatar';
import clsx from 'clsx';
import type { CSSProperties, FC } from 'react';
import type { CSSProperties } from 'react';
import * as style from './style.css';
export type UserAvatar = {
export interface UserAvatar {
size?: number;
url?: string;
name?: string;
className?: string;
style?: CSSProperties;
};
}
export const UserAvatar: FC<UserAvatar> = ({
export const UserAvatar = ({
size = 20,
style: propsStyles = {},
url,
name,
className,
}) => {
}: UserAvatar) => {
return (
<Avatar.Root
style={{

View File

@@ -3,29 +3,26 @@ import * as RadixAvatar from '@radix-ui/react-avatar';
import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import clsx from 'clsx';
import type React from 'react';
import { DefaultAvatar } from './default-avatar';
import { avatarImageStyle, avatarStyle } from './index.css';
export type WorkspaceAvatarProps = {
export interface WorkspaceAvatarProps {
size?: number;
workspace: Workspace | null;
className?: string;
};
}
export type BlockSuiteWorkspaceAvatar = Omit<
WorkspaceAvatarProps,
'workspace'
> & {
export interface BlockSuiteWorkspaceAvatar
extends Omit<WorkspaceAvatarProps, 'workspace'> {
workspace: Workspace;
};
}
export const BlockSuiteWorkspaceAvatar: React.FC<BlockSuiteWorkspaceAvatar> = ({
export const BlockSuiteWorkspaceAvatar = ({
size,
workspace,
...props
}) => {
}: BlockSuiteWorkspaceAvatar) => {
const [avatar] = useBlockSuiteWorkspaceAvatarUrl(workspace);
const [name] = useBlockSuiteWorkspaceName(workspace);
@@ -46,11 +43,11 @@ export const BlockSuiteWorkspaceAvatar: React.FC<BlockSuiteWorkspaceAvatar> = ({
);
};
export const WorkspaceAvatar: React.FC<WorkspaceAvatarProps> = ({
export const WorkspaceAvatar = ({
size = 20,
workspace,
...props
}) => {
}: WorkspaceAvatarProps) => {
if (workspace) {
return (
<BlockSuiteWorkspaceAvatar {...props} size={size} workspace={workspace} />

View File

@@ -11,26 +11,26 @@ import {
useSensors,
} from '@dnd-kit/core';
import { SortableContext, useSortable } from '@dnd-kit/sortable';
import type { CSSProperties, FC } from 'react';
import type { CSSProperties } from 'react';
import { useMemo } from 'react';
import { WorkspaceCard } from '../../components/card/workspace-card';
import { workspaceItemStyle } from './index.css';
export type WorkspaceListProps = {
export interface WorkspaceListProps {
disabled?: boolean;
currentWorkspaceId: string | null;
items: (AffineCloudWorkspace | LocalWorkspace)[];
onClick: (workspaceId: string) => void;
onSettingClick: (workspaceId: string) => void;
onDragEnd: (event: DragEndEvent) => void;
};
}
const SortableWorkspaceItem: FC<
Omit<WorkspaceListProps, 'items'> & {
item: RootWorkspaceMetadata;
}
> = props => {
interface SortableWorkspaceItemProps extends Omit<WorkspaceListProps, 'items'> {
item: RootWorkspaceMetadata;
}
const SortableWorkspaceItem = (props: SortableWorkspaceItemProps) => {
const { setNodeRef, attributes, listeners, transform } = useSortable({
id: props.item.id,
});
@@ -63,7 +63,7 @@ const SortableWorkspaceItem: FC<
);
};
export const WorkspaceList: FC<WorkspaceListProps> = props => {
export const WorkspaceList = (props: WorkspaceListProps) => {
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: {

View File

@@ -1,26 +1,27 @@
import { clsx } from 'clsx';
import type {
FC,
HTMLAttributes,
PropsWithChildren,
ReactElement,
ReactNode,
} from 'react';
import { AppSidebarFallback } from '../app-sidebar';
import { appStyle, mainContainerStyle, toolStyle } from './index.css';
export type WorkspaceRootProps = PropsWithChildren<{
export interface WorkspaceRootProps {
resizing?: boolean;
useNoisyBackground?: boolean;
useBlurBackground?: boolean;
}>;
children: ReactNode;
}
export const AppContainer: FC<WorkspaceRootProps> = ({
export const AppContainer = ({
resizing,
useNoisyBackground,
useBlurBackground,
children,
}) => {
}: WorkspaceRootProps) => {
const noisyBackground = useNoisyBackground && environment.isDesktop;
return (
<div
@@ -36,18 +37,17 @@ export const AppContainer: FC<WorkspaceRootProps> = ({
);
};
export type MainContainerProps = PropsWithChildren<{
export interface MainContainerProps extends HTMLAttributes<HTMLDivElement> {
className?: string;
padding?: boolean;
}> &
HTMLAttributes<HTMLDivElement>;
}
export const MainContainer = ({
className,
padding,
children,
...props
}: MainContainerProps): ReactElement => {
}: PropsWithChildren<MainContainerProps>): ReactElement => {
return (
<div
{...props}

View File

@@ -1,6 +1,5 @@
import clsx from 'clsx';
import {
type FC,
forwardRef,
type HTMLAttributes,
type PropsWithChildren,
@@ -10,6 +9,7 @@ import {
import { Loading } from '../loading';
import { button, buttonIcon } from './style.css';
export type ButtonType =
| 'default'
| 'primary'
@@ -18,18 +18,21 @@ export type ButtonType =
| 'warning'
| 'success'
| 'processing';
export type ButtonSize = 'default' | 'large' | 'extraLarge';
export type ButtonProps = PropsWithChildren &
Omit<HTMLAttributes<HTMLButtonElement>, 'type'> & {
type?: ButtonType;
disabled?: boolean;
icon?: ReactElement;
iconPosition?: 'start' | 'end';
shape?: 'default' | 'round' | 'circle';
block?: boolean;
size?: ButtonSize;
loading?: boolean;
};
export interface ButtonProps
extends Omit<HTMLAttributes<HTMLButtonElement>, 'type'> {
type?: ButtonType;
disabled?: boolean;
icon?: ReactElement;
iconPosition?: 'start' | 'end';
shape?: 'default' | 'round' | 'circle';
block?: boolean;
size?: ButtonSize;
loading?: boolean;
}
const defaultProps = {
type: 'default',
disabled: false,
@@ -39,7 +42,7 @@ const defaultProps = {
loading: false,
};
const ButtonIcon: FC<ButtonProps> = props => {
const ButtonIcon = (props: PropsWithChildren<ButtonProps>) => {
const {
size,
icon,
@@ -65,6 +68,7 @@ const ButtonIcon: FC<ButtonProps> = props => {
</div>
);
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const {

View File

@@ -1,14 +1,13 @@
import { assignInlineVars } from '@vanilla-extract/dynamic';
import type { FC } from 'react';
import { loading, speedVar } from './styles.css';
export type LoadingProps = {
export interface LoadingProps {
size?: number;
speed?: number;
};
}
export const Loading: FC<LoadingProps> = ({ size, speed = 1.2 }) => {
export const Loading = ({ size, speed = 1.2 }: LoadingProps) => {
return (
<svg
className={loading}

View File

@@ -115,21 +115,26 @@ export const toast = (
element.animate(fadeIn, options);
setTimeout(async () => {
setTimeout(() => {
const animation = element.animate(
// fade out
fadeIn.reverse(),
options
);
await animation.finished;
element.style.maxHeight = '0';
element.style.margin = '0';
element.style.padding = '0';
// wait for transition
// ToastContainer = null;
element.addEventListener('transitionend', () => {
element.remove();
});
animation.finished
.then(() => {
element.style.maxHeight = '0';
element.style.margin = '0';
element.style.padding = '0';
// wait for transition
// ToastContainer = null;
element.addEventListener('transitionend', () => {
element.remove();
});
})
.catch(err => {
console.error(err);
});
}, duration);
return element;
};

View File

@@ -5,8 +5,7 @@
"compilerOptions": {
"composite": true,
"noEmit": false,
"outDir": "lib",
"types": ["@affine/env"]
"outDir": "lib"
},
"references": [
{

View File

@@ -8,5 +8,5 @@
"devDependencies": {
"@types/debug": "^4.1.8"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -4,9 +4,8 @@
"type": "module",
"main": "./src/index.ts",
"module": "./src/index.ts",
"types": "./src/global.ts",
"devDependencies": {
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"react": "18.2.0",
"react-dom": "18.2.0",
"zod": "^3.21.4"
@@ -28,5 +27,5 @@
"dependencies": {
"lit": "^2.7.6"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -1,60 +1,10 @@
/// <reference types="@blocksuite/global" />
import { assertEquals } from '@blocksuite/global/utils';
import type {
DBHandlerManager,
DebugHandlerManager,
DialogHandlerManager,
ExportHandlerManager,
UIHandlerManager,
UnwrapManagerHandlerToClientSide,
UpdaterHandlerManager,
WorkspaceHandlerManager,
} from '@toeverything/infra';
import { z } from 'zod';
import { isBrowser, isDesktop, isServer } from './constant.js';
import { isValidIPAddress } from './is-valid-ip-address.js';
import { UaHelper } from './ua-helper.js';
declare global {
interface Window {
appInfo: {
electron: boolean;
};
apis: {
db: UnwrapManagerHandlerToClientSide<DBHandlerManager>;
debug: UnwrapManagerHandlerToClientSide<DebugHandlerManager>;
dialog: UnwrapManagerHandlerToClientSide<DialogHandlerManager>;
export: UnwrapManagerHandlerToClientSide<ExportHandlerManager>;
ui: UnwrapManagerHandlerToClientSide<UIHandlerManager>;
updater: UnwrapManagerHandlerToClientSide<UpdaterHandlerManager>;
workspace: UnwrapManagerHandlerToClientSide<WorkspaceHandlerManager>;
};
events: any;
}
interface WindowEventMap {
'migration-done': CustomEvent;
}
// eslint-disable-next-line no-var
var $migrationDone: boolean;
// eslint-disable-next-line no-var
var platform: Platform | undefined;
// eslint-disable-next-line no-var
var environment: Environment;
// eslint-disable-next-line no-var
var runtimeConfig: RuntimeConfig;
// eslint-disable-next-line no-var
var $AFFINE_SETUP: boolean | undefined;
// eslint-disable-next-line no-var
var editorVersion: string | undefined;
// eslint-disable-next-line no-var
var prefixUrl: string;
// eslint-disable-next-line no-var
var websocketPrefixUrl: string;
}
export const blockSuiteFeatureFlags = z.object({
enable_database: z.boolean(),
enable_drag_handle: z.boolean(),

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/graphql",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"description": "Autogenerated GraphQL client for affine.pro",
"license": "MPL-2.0",
"type": "module",

View File

@@ -10,12 +10,12 @@
"@toeverything/y-indexeddb": "workspace:*"
},
"devDependencies": {
"@blocksuite/block-std": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly"
"@blocksuite/block-std": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly"
},
"peerDependencies": {
"@blocksuite/block-std": "*",
@@ -25,5 +25,5 @@
"@blocksuite/lit": "*",
"@blocksuite/store": "*"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -6,7 +6,7 @@ import 'fake-indexeddb/auto';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { assertExists } from '@blocksuite/global/utils';
import type { Page } from '@blocksuite/store';
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
import { Schema, Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
import { renderHook } from '@testing-library/react';
import { useAtomValue } from 'jotai';
import { describe, expect, test } from 'vitest';
@@ -19,10 +19,11 @@ import { useBlockSuiteWorkspacePageTitle } from '../use-block-suite-workspace-pa
let blockSuiteWorkspace: BlockSuiteWorkspace;
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
beforeEach(async () => {
blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test' })
.register(AffineSchemas)
.register(__unstableSchemas);
blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test', schema });
const initPage = async (page: Page) => {
await page.waitForLoaded();
expect(page).not.toBeNull();

View File

@@ -5,7 +5,7 @@ import 'fake-indexeddb/auto';
import { initEmptyPage } from '@affine/env/blocksuite';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { Workspace } from '@blocksuite/store';
import { Schema, Workspace } from '@blocksuite/store';
import { renderHook } from '@testing-library/react';
import { beforeEach, describe, expect, test } from 'vitest';
@@ -14,12 +14,14 @@ import { useBlockSuiteWorkspaceHelper } from '../use-block-suite-workspace-helpe
let blockSuiteWorkspace: Workspace;
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
beforeEach(async () => {
blockSuiteWorkspace = new Workspace({
id: 'test',
})
.register(AffineSchemas)
.register(__unstableSchemas);
schema,
});
await initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page0' }));
await initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page1' }));
await initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page2' }));

View File

@@ -37,5 +37,5 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -87,23 +87,22 @@ const main = async () => {
language => language.completeRate > 0.4
);
availableLanguages
for (const language of availableLanguages
// skip base language
.filter(i => !i.base)
.forEach(async language => {
await fs.writeFile(
path.resolve(RES_DIR, `${language.tag}.json`),
JSON.stringify(
{
'// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.':
'',
...flattenTranslation(language.translations),
},
null,
INDENT
) + '\n'
);
});
.filter(i => !i.base)) {
await fs.writeFile(
path.resolve(RES_DIR, `${language.tag}.json`),
JSON.stringify(
{
'// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.':
'',
...flattenTranslation(language.translations),
},
null,
INDENT
) + '\n'
);
}
console.log('Generating meta data...');
const code = `// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.

View File

@@ -127,11 +127,11 @@ const main = async () => {
return;
}
diff.add.forEach(async key => {
for (const key of diff.add) {
const val = flatLocalTranslations[key];
console.log(`Creating new key: ${key} -> ${val}`);
await createsNewKey(key, { [BASE_LANGUAGES]: val });
});
}
// TODO remove unused tags from used keys

View File

@@ -50,15 +50,15 @@
},
"dependencies": {
"@affine/sdk": "workspace:*",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"jotai": "^2.2.2",
"zod": "^3.21.4"
},
"devDependencies": {
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"async-call-rpc": "^6.3.1",
"electron": "link:../../apps/electron/node_modules/electron",
"react": "^18.2.0",
@@ -87,5 +87,5 @@
"optional": true
}
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -1,7 +1,7 @@
/**
* @vitest-environment happy-dom
*/
import { Workspace } from '@blocksuite/store';
import { Schema, Workspace } from '@blocksuite/store';
import { renderHook } from '@testing-library/react';
import { getDefaultStore } from 'jotai/vanilla';
import { expect, test, vi } from 'vitest';
@@ -20,6 +20,7 @@ test('useStaticBlockSuiteWorkspace', async () => {
let connected = false;
const connect = vi.fn(() => (connected = true));
const workspace = new Workspace({
schema: new Schema(),
id: '1',
providerCreators: [
() => ({

View File

@@ -116,7 +116,7 @@ function getMainAPIs() {
}
const helperPort$ = new Promise<MessagePort>(resolve =>
ipcRenderer.on('helper-connection', async e => {
ipcRenderer.on('helper-connection', e => {
console.info('[preload] helper-connection', e);
resolve(e.ports[0]);
})

View File

@@ -105,9 +105,9 @@ export type DBHandlers = {
key: string,
data: Uint8Array
) => Promise<void>;
getBlob: (workspaceId: string, key: string) => Promise<any>;
getBlob: (workspaceId: string, key: string) => Promise<Buffer | null>;
deleteBlob: (workspaceId: string, key: string) => Promise<void>;
getBlobKeys: (workspaceId: string) => Promise<any>;
getBlobKeys: (workspaceId: string) => Promise<string[]>;
getDefaultStorageLocation: () => Promise<string>;
};
@@ -116,13 +116,55 @@ export type DebugHandlers = {
logFilePath: () => Promise<string>;
};
export type ErrorMessage =
| 'DB_FILE_ALREADY_LOADED'
| 'DB_FILE_PATH_INVALID'
| 'DB_FILE_INVALID'
| 'DB_FILE_MIGRATION_FAILED'
| 'FILE_ALREADY_EXISTS'
| 'UNKNOWN_ERROR';
export interface LoadDBFileResult {
workspaceId?: string;
error?: ErrorMessage;
canceled?: boolean;
}
export interface SaveDBFileResult {
filePath?: string;
canceled?: boolean;
error?: ErrorMessage;
}
export interface SelectDBFileLocationResult {
filePath?: string;
error?: ErrorMessage;
canceled?: boolean;
}
export interface MoveDBFileResult {
filePath?: string;
error?: ErrorMessage;
canceled?: boolean;
}
// provide a backdoor to set dialog path for testing in playwright
export interface FakeDialogResult {
canceled?: boolean;
filePath?: string;
filePaths?: string[];
}
export type DialogHandlers = {
revealDBFile: (workspaceId: string) => Promise<any>;
loadDBFile: () => Promise<any>;
saveDBFileAs: (workspaceId: string) => Promise<any>;
moveDBFile: (workspaceId: string, dbFileLocation?: string) => Promise<any>;
selectDBFileLocation: () => Promise<any>;
setFakeDialogResult: (result: any) => Promise<any>;
revealDBFile: (workspaceId: string) => Promise<void>;
loadDBFile: () => Promise<LoadDBFileResult>;
saveDBFileAs: (workspaceId: string) => Promise<SaveDBFileResult>;
moveDBFile: (
workspaceId: string,
dbFileLocation?: string
) => Promise<MoveDBFileResult>;
selectDBFileLocation: () => Promise<SelectDBFileLocationResult>;
setFakeDialogResult: (result: any) => Promise<FakeDialogResult>;
};
export type UIHandlers = {

View File

@@ -6,12 +6,12 @@
"jotai": "^2.2.2"
},
"devDependencies": {
"@blocksuite/block-std": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/editor": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/lit": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/block-std": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/editor": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/lit": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"lottie-web": "^5.12.2"
},
"peerDependencies": {
@@ -23,5 +23,5 @@
"@blocksuite/store": "*",
"lottie-web": "*"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -38,5 +38,5 @@
"test": "cross-env TS_NODE_TRANSPILE_ONLY=1 TS_NODE_PROJECT=./tsconfig.json node --test --loader ts-node/esm --experimental-specifier-resolution=node ./__tests__/**/*.mts",
"version": "napi version"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -1,7 +1,7 @@
{
"name": "@affine/plugin-cli",
"type": "module",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"bin": {
"af": "./src/af.mjs"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/sdk",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"type": "module",
"scripts": {
"build": "vite build",
@@ -22,9 +22,9 @@
"dist"
],
"dependencies": {
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/global": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/global": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"jotai": "^2.2.2",
"zod": "^3.21.4"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/storage",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"engines": {
"node": ">= 10.16.0 < 11 || >= 11.8.0"
},

View File

@@ -6,5 +6,5 @@
"./*.md": "./*.md",
"./preloading.json": "./preloading.json"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@affine/workers",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"private": true,
"scripts": {
"dev": "wrangler dev"

View File

@@ -34,5 +34,5 @@
"@types/ws": "^8.5.5",
"ws": "^8.13.0"
},
"version": "0.8.0-canary.10"
"version": "0.8.0-canary.11"
}

View File

@@ -7,11 +7,15 @@ import type { WorkspaceCRUD } from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { assertExists } from '@blocksuite/global/utils';
import { Workspace } from '@blocksuite/store';
import { Schema, Workspace } from '@blocksuite/store';
import { afterEach, assertType, describe, expect, test } from 'vitest';
import { CRUD } from '../crud';
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
afterEach(() => {
localStorage.clear();
});
@@ -30,14 +34,12 @@ describe('crud', () => {
test('delete not exist', async () => {
await expect(async () =>
CRUD.delete(new Workspace({ id: 'test' }))
CRUD.delete(new Workspace({ id: 'test', schema }))
).rejects.toThrowError();
});
test('create & delete', async () => {
const workspace = new Workspace({ id: 'test' })
.register(AffineSchemas)
.register(__unstableSchemas);
const workspace = new Workspace({ id: 'test', schema });
const page = workspace.createPage({ id: 'page0' });
await page.waitForLoaded();
const pageBlockId = page.addBlock('affine:page', {

View File

@@ -6,6 +6,7 @@ import type { DocProviderCreator, StoreOptions } from '@blocksuite/store';
import {
createIndexeddbStorage,
Generator,
Schema,
Workspace,
} from '@blocksuite/store';
import { INTERNAL_BLOCKSUITE_HASH_MAP } from '@toeverything/infra/__internal__/workspace';
@@ -44,6 +45,10 @@ type SubdocEvent = {
const docUpdateCallbackWeakMap = new WeakMap<Doc, UpdateCallback>();
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
const createMonitor = (doc: Doc) => {
const onUpdate: UpdateCallback = (_, origin) => {
if (process.env.NODE_ENV === 'development') {
@@ -118,9 +123,8 @@ export function getOrCreateWorkspace(
providerCreators: typeof window === 'undefined' ? [] : providerCreators,
blobStorages: blobStorages,
idGenerator,
})
.register(AffineSchemas)
.register(__unstableSchemas);
schema,
});
createMonitor(workspace.doc);
setEditorFlags(workspace);
INTERNAL_BLOCKSUITE_HASH_MAP.set(id, workspace);

View File

@@ -8,7 +8,7 @@ import type {
LocalIndexedDBDownloadProvider,
} from '@affine/env/workspace';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { Workspace } from '@blocksuite/store';
import { Schema, Workspace } from '@blocksuite/store';
import { afterEach, describe, expect, test } from 'vitest';
import {
@@ -16,6 +16,10 @@ import {
createIndexedDBDownloadProvider,
} from '..';
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
afterEach(() => {
globalThis.localStorage.clear();
globalThis.indexedDB.deleteDatabase('affine-local');
@@ -28,8 +32,8 @@ describe('download provider', () => {
const workspace = new Workspace({
id: 'test',
isSSR: true,
schema,
});
workspace.register(AffineSchemas).register(__unstableSchemas);
const provider = createIndexedDBBackgroundProvider(
workspace.id,
workspace.doc,
@@ -57,8 +61,8 @@ describe('download provider', () => {
const workspace = new Workspace({
id: 'test',
isSSR: true,
schema,
});
workspace.register(AffineSchemas).register(__unstableSchemas);
const provider = createIndexedDBDownloadProvider(
workspace.id,
workspace.doc,

View File

@@ -5,7 +5,7 @@ import type {
import { getDoc } from '@affine/y-provider';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import type { Y as YType } from '@blocksuite/store';
import { uuidv4, Workspace } from '@blocksuite/store';
import { Schema, uuidv4, Workspace } from '@blocksuite/store';
import { setTimeout } from 'timers/promises';
import { beforeEach, describe, expect, test, vi } from 'vitest';
@@ -70,13 +70,17 @@ vi.stubGlobal('environment', {
isDesktop: true,
});
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
beforeEach(() => {
id = uuidv4();
workspace = new Workspace({
id,
isSSR: true,
schema,
});
workspace.register(AffineSchemas).register(__unstableSchemas);
provider = createSQLiteProvider(workspace.id, workspace.doc, {
awareness: workspace.awarenessStore.awareness,
}) as SQLiteProvider;

View File

@@ -106,14 +106,15 @@ export const createSQLiteDBDownloadProvider: DocProviderCreator = (
cleanup: () => {
// todo
},
sync: async () => {
sync: () => {
logger.info('connect sqlite download provider', id);
try {
await syncUpdates(rootDoc);
_resolve();
} catch (error) {
_reject(error);
}
syncUpdates(rootDoc)
.then(() => {
_resolve();
})
.catch(error => {
_reject(error);
});
},
};
};

View File

@@ -1,7 +1,7 @@
{
"name": "@toeverything/y-indexeddb",
"type": "module",
"version": "0.8.0-canary.10",
"version": "0.8.0-canary.11",
"description": "IndexedDB database adapter for Yjs",
"repository": "toeverything/AFFiNE",
"author": "toeverything",
@@ -37,8 +37,8 @@
},
"devDependencies": {
"@affine/y-provider": "workspace:*",
"@blocksuite/blocks": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/store": "0.0.0-20230802200139-381599c0-nightly",
"@blocksuite/blocks": "0.0.0-20230804190636-37f66904-nightly",
"@blocksuite/store": "0.0.0-20230804190636-37f66904-nightly",
"vite": "^4.4.7",
"vite-plugin-dts": "3.3.1",
"y-indexeddb": "^9.0.11"

View File

@@ -8,7 +8,7 @@ import { setTimeout } from 'node:timers/promises';
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
import { assertExists } from '@blocksuite/global/utils';
import type { Page } from '@blocksuite/store';
import { uuidv4, Workspace } from '@blocksuite/store';
import { Schema, uuidv4, Workspace } from '@blocksuite/store';
import { openDB } from 'idb';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { applyUpdate, Doc, encodeStateAsUpdate } from 'yjs';
@@ -56,13 +56,17 @@ let id: string;
let workspace: Workspace;
const rootDBName = DEFAULT_DB_NAME;
const schema = new Schema();
schema.register(AffineSchemas).register(__unstableSchemas);
beforeEach(() => {
id = uuidv4();
workspace = new Workspace({
id,
isSSR: true,
schema,
});
workspace.register(AffineSchemas).register(__unstableSchemas);
});
afterEach(() => {
@@ -109,9 +113,8 @@ describe('indexeddb provider', () => {
expect(data.id).toBe(id);
const testWorkspace = new Workspace({
id: 'test',
})
.register(AffineSchemas)
.register(__unstableSchemas);
schema,
});
// data should only contain updates for the root doc
data.updates.forEach(({ update }) => {
Workspace.Y.applyUpdate(testWorkspace.doc, update);
@@ -379,8 +382,8 @@ describe('subDoc', () => {
const newWorkspace = new Workspace({
id,
isSSR: true,
schema,
});
newWorkspace.register(AffineSchemas).register(__unstableSchemas);
const provider = createIndexedDBProvider(newWorkspace.doc, rootDBName);
provider.connect();
await setTimeout(200);
@@ -419,8 +422,8 @@ describe('utils', () => {
const newWorkspace = new Workspace({
id,
isSSR: true,
schema,
});
newWorkspace.register(AffineSchemas).register(__unstableSchemas);
applyUpdate(newWorkspace.doc, update);
await setTimeout();
expect(workspace.doc.toJSON()['meta']).toEqual(

View File

@@ -1,4 +1,4 @@
import type { DBSchema, IDBPDatabase } from 'idb/build/entry';
import type { DBSchema, IDBPDatabase } from 'idb';
export const dbVersion = 1;
export const DEFAULT_DB_NAME = 'affine-local';

Some files were not shown because too many files have changed in this diff Show More