mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 11:58:41 +00:00
Compare commits
12 Commits
v0.8.0-can
...
v0.8.0-can
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36bd0b02d0 | ||
|
|
3a92c4f798 | ||
|
|
97de0ef5b4 | ||
|
|
bbf5f0efe0 | ||
|
|
ea76936508 | ||
|
|
f076cb0ead | ||
|
|
0f230253a8 | ||
|
|
13d2dde501 | ||
|
|
65fc0ed59c | ||
|
|
7ec4b8fb8c | ||
|
|
6415f0093b | ||
|
|
5795020403 |
@@ -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,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
13
README.md
13
README.md
@@ -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 -->
|
||||
|
||||
[?style=flat-square&logoColor=white&logo=affine>)](https://app.affine.pro)
|
||||
[](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/)
|
||||
[](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
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Ftoeverything%2FAFFiNE?ref=badge_large)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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']());
|
||||
|
||||
@@ -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]());
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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:
|
||||
@@ -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.
@@ -10,7 +10,8 @@
|
||||
"skipLibCheck": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"jsx": "react-jsx"
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
},
|
||||
"include": ["src", "entries.ts"],
|
||||
"references": [
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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
54
packages/@types/env/__all.d.ts
vendored
Normal 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
11
packages/@types/env/package.json
vendored
Normal 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"
|
||||
}
|
||||
@@ -20,5 +20,5 @@
|
||||
"peerDependencies": {
|
||||
"ts-node": "*"
|
||||
},
|
||||
"version": "0.8.0-canary.10"
|
||||
"version": "0.8.0-canary.11"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)',
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>)} />
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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={{
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"noEmit": false,
|
||||
"outDir": "lib",
|
||||
"types": ["@affine/env"]
|
||||
"outDir": "lib"
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.8"
|
||||
},
|
||||
"version": "0.8.0-canary.10"
|
||||
"version": "0.8.0-canary.11"
|
||||
}
|
||||
|
||||
5
packages/env/package.json
vendored
5
packages/env/package.json
vendored
@@ -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"
|
||||
}
|
||||
|
||||
50
packages/env/src/global.ts
vendored
50
packages/env/src/global.ts
vendored
@@ -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(),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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' }));
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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: [
|
||||
() => ({
|
||||
|
||||
@@ -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]);
|
||||
})
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"./*.md": "./*.md",
|
||||
"./preloading.json": "./preloading.json"
|
||||
},
|
||||
"version": "0.8.0-canary.10"
|
||||
"version": "0.8.0-canary.11"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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', {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user