mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-10 21:48:48 +08:00
style: enable no-non-null-assertion rule (#2723)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
(cherry picked from commit 18dc427bc3)
This commit is contained in:
@@ -6,3 +6,4 @@ storybook-static
|
|||||||
affine-out
|
affine-out
|
||||||
_next
|
_next
|
||||||
lib
|
lib
|
||||||
|
.eslintrc.js
|
||||||
|
|||||||
+18
-17
@@ -1,3 +1,5 @@
|
|||||||
|
const { readdirSync, statSync } = require('fs');
|
||||||
|
|
||||||
const createPattern = packageName => [
|
const createPattern = packageName => [
|
||||||
{
|
{
|
||||||
group: ['**/dist', '**/dist/**'],
|
group: ['**/dist', '**/dist/**'],
|
||||||
@@ -21,22 +23,14 @@ const createPattern = packageName => [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const allPackages = [
|
const pkgs = readdirSync('./packages').filter(pkg => {
|
||||||
'cli',
|
return statSync(`./packages/${pkg}`).isDirectory();
|
||||||
'component',
|
});
|
||||||
'debug',
|
const apps = readdirSync('./apps').filter(pkg => {
|
||||||
'env',
|
return statSync(`./apps/${pkg}`).isDirectory();
|
||||||
'graphql',
|
});
|
||||||
'hooks',
|
|
||||||
'i18n',
|
const allPackages = pkgs.concat(apps);
|
||||||
'jotai',
|
|
||||||
'native',
|
|
||||||
'plugin-infra',
|
|
||||||
'templates',
|
|
||||||
'theme',
|
|
||||||
'workspace',
|
|
||||||
'y-indexeddb',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('eslint').Linter.Config}
|
* @type {import('eslint').Linter.Config}
|
||||||
@@ -67,6 +61,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
ecmaVersion: 'latest',
|
ecmaVersion: 'latest',
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
|
project: './tsconfig.eslint.json',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
'react',
|
'react',
|
||||||
@@ -83,7 +78,7 @@ const config = {
|
|||||||
'no-cond-assign': 'off',
|
'no-cond-assign': 'off',
|
||||||
'react/prop-types': 'off',
|
'react/prop-types': 'off',
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'@typescript-eslint/no-empty-function': 'off',
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
'@typescript-eslint/no-unused-vars': [
|
'@typescript-eslint/no-unused-vars': [
|
||||||
@@ -136,6 +131,12 @@ const config = {
|
|||||||
'@typescript-eslint/no-var-requires': 0,
|
'@typescript-eslint/no-var-requires': 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['**/__tests__/**/*', '**/*.stories.tsx'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
...allPackages.map(pkg => ({
|
...allPackages.map(pkg => ({
|
||||||
files: [`packages/${pkg}/src/**/*.ts`, `packages/${pkg}/src/**/*.tsx`],
|
files: [`packages/${pkg}/src/**/*.ts`, `packages/${pkg}/src/**/*.tsx`],
|
||||||
rules: {
|
rules: {
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ export abstract class BaseSQLiteAdapter {
|
|||||||
db: SqliteConnection | null = null;
|
db: SqliteConnection | null = null;
|
||||||
abstract role: string;
|
abstract role: string;
|
||||||
|
|
||||||
constructor(public readonly path: string) {
|
constructor(public readonly path: string) {}
|
||||||
logger.info(`[SQLiteAdapter]`, 'path:', path);
|
|
||||||
}
|
|
||||||
|
|
||||||
async connectIfNeeded() {
|
async connectIfNeeded() {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ function getWorkspaceDB$(id: string) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
return db$Map.get(id)!;
|
return db$Map.get(id)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ export class SecondaryWorkspaceSQLiteDB extends BaseSQLiteAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.firstConnected = true;
|
this.firstConnected = true;
|
||||||
const { db } = this;
|
|
||||||
|
|
||||||
const onUpstreamUpdate = (update: Uint8Array, origin: YOrigin) => {
|
const onUpstreamUpdate = (update: Uint8Array, origin: YOrigin) => {
|
||||||
if (origin === 'renderer') {
|
if (origin === 'renderer') {
|
||||||
@@ -118,8 +117,8 @@ export class SecondaryWorkspaceSQLiteDB extends BaseSQLiteAdapter {
|
|||||||
|
|
||||||
const onSelfUpdate = (update: Uint8Array, origin: YOrigin) => {
|
const onSelfUpdate = (update: Uint8Array, origin: YOrigin) => {
|
||||||
// for self update from upstream, we need to push it to external DB
|
// for self update from upstream, we need to push it to external DB
|
||||||
if (origin === 'upstream') {
|
if (origin === 'upstream' && this.db) {
|
||||||
this.addUpdateToUpdateQueue(db!, update);
|
this.addUpdateToUpdateQueue(this.db, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin === 'self') {
|
if (origin === 'self') {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export const registerUpdater = async () => {
|
|||||||
// register events for checkForUpdatesAndNotify
|
// register events for checkForUpdatesAndNotify
|
||||||
_autoUpdater.on('update-available', info => {
|
_autoUpdater.on('update-available', info => {
|
||||||
if (allowAutoUpdate) {
|
if (allowAutoUpdate) {
|
||||||
_autoUpdater!.downloadUpdate();
|
_autoUpdater?.downloadUpdate();
|
||||||
logger.info('Update available, downloading...', info);
|
logger.info('Update available, downloading...', info);
|
||||||
}
|
}
|
||||||
updaterSubjects.updateAvailable.next({
|
updaterSubjects.updateAvailable.next({
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export function getRequestResponseFromContext(context: ExecutionContext) {
|
|||||||
}>();
|
}>();
|
||||||
return {
|
return {
|
||||||
req: gqlContext.req,
|
req: gqlContext.req,
|
||||||
res: gqlContext.req.res!,
|
res: gqlContext.req.res,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'http': {
|
case 'http': {
|
||||||
@@ -37,7 +37,7 @@ export function getRequestResponseFromHost(host: ArgumentsHost) {
|
|||||||
}>();
|
}>();
|
||||||
return {
|
return {
|
||||||
req: gqlContext.req,
|
req: gqlContext.req,
|
||||||
res: gqlContext.req.res!,
|
res: gqlContext.req.res,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'http': {
|
case 'http': {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
|||||||
import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons';
|
import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { atom, useAtomValue, useSetAtom } from 'jotai';
|
import { atom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
import { startTransition } from 'react';
|
import { startTransition, useCallback } from 'react';
|
||||||
|
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
import {
|
import {
|
||||||
@@ -50,53 +50,67 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
|||||||
const downloadProgress = useAtomValue(downloadProgressAtom);
|
const downloadProgress = useAtomValue(downloadProgressAtom);
|
||||||
const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
|
const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
|
||||||
|
|
||||||
const onDismissCurrentChangelog = () => {
|
const onDismissCurrentChangelog = useCallback(() => {
|
||||||
|
if (!currentVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
startTransition(() =>
|
startTransition(() =>
|
||||||
setChangelogCheckAtom(mapping => {
|
setChangelogCheckAtom(mapping => {
|
||||||
return {
|
return {
|
||||||
...mapping,
|
...mapping,
|
||||||
[currentVersion!]: true,
|
[currentVersion]: true,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
}, [currentVersion, setChangelogCheckAtom]);
|
||||||
|
const onClickUpdate = useCallback(() => {
|
||||||
|
if (updateReady) {
|
||||||
|
window.apis?.updater.quitAndInstall();
|
||||||
|
} else if (updateAvailable) {
|
||||||
|
if (updateAvailable.allowAutoUpdate) {
|
||||||
|
// wait for download to finish
|
||||||
|
} else {
|
||||||
|
window.open(
|
||||||
|
`https://github.com/toeverything/AFFiNE/releases/tag/v${currentVersion}`,
|
||||||
|
'_blank'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (currentChangelogUnread) {
|
||||||
|
window.open(config.changelogUrl, '_blank');
|
||||||
|
onDismissCurrentChangelog();
|
||||||
|
} else {
|
||||||
|
throw new Unreachable();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
currentChangelogUnread,
|
||||||
|
currentVersion,
|
||||||
|
onDismissCurrentChangelog,
|
||||||
|
updateAvailable,
|
||||||
|
updateReady,
|
||||||
|
]);
|
||||||
|
|
||||||
if (!updateAvailable && !currentChangelogUnread) {
|
if (!updateAvailable && !currentChangelogUnread) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateAvailableNode = updateAvailable
|
||||||
|
? updateAvailable.allowAutoUpdate
|
||||||
|
? renderUpdateAvailableAllowAutoUpdate()
|
||||||
|
: renderUpdateAvailableNotAllowAutoUpdate()
|
||||||
|
: null;
|
||||||
|
const whatsNew =
|
||||||
|
!updateAvailable && currentChangelogUnread ? renderWhatsNew() : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
style={style}
|
style={style}
|
||||||
className={clsx([styles.root, className])}
|
className={clsx([styles.root, className])}
|
||||||
data-has-update={updateAvailable ? 'true' : 'false'}
|
data-has-update={updateAvailable ? 'true' : 'false'}
|
||||||
data-disabled={updateAvailable?.allowAutoUpdate && !updateReady}
|
data-disabled={updateAvailable?.allowAutoUpdate && !updateReady}
|
||||||
onClick={() => {
|
onClick={onClickUpdate}
|
||||||
if (updateReady) {
|
|
||||||
window.apis?.updater.quitAndInstall();
|
|
||||||
} else if (updateAvailable) {
|
|
||||||
if (updateAvailable.allowAutoUpdate) {
|
|
||||||
// wait for download to finish
|
|
||||||
} else {
|
|
||||||
window.open(
|
|
||||||
`https://github.com/toeverything/AFFiNE/releases/tag/v${currentVersion}`,
|
|
||||||
'_blank'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (currentChangelogUnread) {
|
|
||||||
window.open(config.changelogUrl, '_blank');
|
|
||||||
onDismissCurrentChangelog();
|
|
||||||
} else {
|
|
||||||
throw new Unreachable();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{updateAvailable &&
|
{updateAvailableNode}
|
||||||
(updateAvailable.allowAutoUpdate
|
{whatsNew}
|
||||||
? renderUpdateAvailableAllowAutoUpdate()
|
|
||||||
: renderUpdateAvailableNotAllowAutoUpdate())}
|
|
||||||
|
|
||||||
{!updateAvailable && currentChangelogUnread && renderWhatsNew()}
|
|
||||||
<div className={styles.particles} aria-hidden="true"></div>
|
<div className={styles.particles} aria-hidden="true"></div>
|
||||||
<span className={styles.halo} aria-hidden="true"></span>
|
<span className={styles.halo} aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
ExportToMarkdownIcon,
|
ExportToMarkdownIcon,
|
||||||
ExportToPdfIcon,
|
ExportToPdfIcon,
|
||||||
} from '@blocksuite/icons';
|
} from '@blocksuite/icons';
|
||||||
import { useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
|
|
||||||
import { Menu, MenuItem } from '../../..';
|
import { Menu, MenuItem } from '../../..';
|
||||||
import type { CommonMenuItemProps } from './types';
|
import type { CommonMenuItemProps } from './types';
|
||||||
@@ -18,35 +18,39 @@ const ExportToPdfMenuItem = ({
|
|||||||
}: CommonMenuItemProps<{ type: 'pdf' }>) => {
|
}: CommonMenuItemProps<{ type: 'pdf' }>) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const contentParserRef = useRef<ContentParser>();
|
const contentParserRef = useRef<ContentParser>();
|
||||||
return (
|
const { currentEditor } = globalThis;
|
||||||
<>
|
const onClickDownloadPDF = useCallback(() => {
|
||||||
{globalThis.currentEditor!.mode === 'page' && (
|
if (!currentEditor) {
|
||||||
<MenuItem
|
return;
|
||||||
data-testid="export-to-pdf"
|
}
|
||||||
onClick={async () => {
|
const contentParser =
|
||||||
if (!contentParserRef.current) {
|
contentParserRef.current ??
|
||||||
contentParserRef.current = new ContentParser(
|
(contentParserRef.current = new ContentParser(currentEditor.page));
|
||||||
globalThis.currentEditor!.page
|
|
||||||
);
|
window.apis?.export
|
||||||
}
|
.savePDFFileAs(
|
||||||
const result = await window.apis?.export.savePDFFileAs(
|
(currentEditor.page.root as PageBlockModel).title.toString()
|
||||||
(
|
)
|
||||||
globalThis.currentEditor!.page.root as PageBlockModel
|
.then(result => {
|
||||||
).title.toString()
|
if (result !== undefined) {
|
||||||
);
|
return;
|
||||||
if (result !== undefined) {
|
}
|
||||||
return;
|
contentParser.exportPdf();
|
||||||
}
|
onSelect?.({ type: 'pdf' });
|
||||||
contentParserRef.current.exportPdf();
|
});
|
||||||
onSelect?.({ type: 'pdf' });
|
}, [currentEditor, onSelect]);
|
||||||
}}
|
if (currentEditor && currentEditor.mode === 'page') {
|
||||||
icon={<ExportToPdfIcon />}
|
return (
|
||||||
>
|
<MenuItem
|
||||||
{t['Export to PDF']()}
|
data-testid="export-to-pdf"
|
||||||
</MenuItem>
|
onClick={onClickDownloadPDF}
|
||||||
)}
|
icon={<ExportToPdfIcon />}
|
||||||
</>
|
>
|
||||||
);
|
{t['Export to PDF']()}
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ExportToHtmlMenuItem = ({
|
const ExportToHtmlMenuItem = ({
|
||||||
@@ -54,19 +58,22 @@ const ExportToHtmlMenuItem = ({
|
|||||||
}: CommonMenuItemProps<{ type: 'html' }>) => {
|
}: CommonMenuItemProps<{ type: 'html' }>) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const contentParserRef = useRef<ContentParser>();
|
const contentParserRef = useRef<ContentParser>();
|
||||||
|
const { currentEditor } = globalThis;
|
||||||
|
const onClickExportHtml = useCallback(() => {
|
||||||
|
if (!currentEditor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!contentParserRef.current) {
|
||||||
|
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||||
|
}
|
||||||
|
contentParserRef.current.exportHtml();
|
||||||
|
onSelect?.({ type: 'html' });
|
||||||
|
}, [onSelect, currentEditor]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data-testid="export-to-html"
|
data-testid="export-to-html"
|
||||||
onClick={() => {
|
onClick={onClickExportHtml}
|
||||||
if (!contentParserRef.current) {
|
|
||||||
contentParserRef.current = new ContentParser(
|
|
||||||
globalThis.currentEditor!.page
|
|
||||||
);
|
|
||||||
}
|
|
||||||
contentParserRef.current.exportHtml();
|
|
||||||
onSelect?.({ type: 'html' });
|
|
||||||
}}
|
|
||||||
icon={<ExportToHtmlIcon />}
|
icon={<ExportToHtmlIcon />}
|
||||||
>
|
>
|
||||||
{t['Export to HTML']()}
|
{t['Export to HTML']()}
|
||||||
@@ -108,19 +115,22 @@ const ExportToMarkdownMenuItem = ({
|
|||||||
}: CommonMenuItemProps<{ type: 'markdown' }>) => {
|
}: CommonMenuItemProps<{ type: 'markdown' }>) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const contentParserRef = useRef<ContentParser>();
|
const contentParserRef = useRef<ContentParser>();
|
||||||
|
const { currentEditor } = globalThis;
|
||||||
|
const onClickExportMarkdown = useCallback(() => {
|
||||||
|
if (!currentEditor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!contentParserRef.current) {
|
||||||
|
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||||
|
}
|
||||||
|
contentParserRef.current.exportMarkdown();
|
||||||
|
onSelect?.({ type: 'markdown' });
|
||||||
|
}, [onSelect, currentEditor]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
data-testid="export-to-markdown"
|
data-testid="export-to-markdown"
|
||||||
onClick={() => {
|
onClick={onClickExportMarkdown}
|
||||||
if (!contentParserRef.current) {
|
|
||||||
contentParserRef.current = new ContentParser(
|
|
||||||
globalThis.currentEditor!.page
|
|
||||||
);
|
|
||||||
}
|
|
||||||
contentParserRef.current.exportMarkdown();
|
|
||||||
onSelect?.({ type: 'markdown' });
|
|
||||||
}}
|
|
||||||
icon={<ExportToMarkdownIcon />}
|
icon={<ExportToMarkdownIcon />}
|
||||||
>
|
>
|
||||||
{t['Export to Markdown']()}
|
{t['Export to Markdown']()}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { useCallback, useState } from 'react';
|
|||||||
import useCollapsed from './hooks/use-collapsed';
|
import useCollapsed from './hooks/use-collapsed';
|
||||||
import useSelectWithKeyboard from './hooks/use-select-with-keyboard';
|
import useSelectWithKeyboard from './hooks/use-select-with-keyboard';
|
||||||
import { TreeNode, TreeNodeWithDnd } from './tree-node';
|
import { TreeNode, TreeNodeWithDnd } from './tree-node';
|
||||||
import type { TreeViewProps } from './types';
|
import type { Node, TreeViewProps } from './types';
|
||||||
import { findNode } from './utils';
|
import { findNode } from './utils';
|
||||||
export const TreeView = <RenderProps,>({
|
export const TreeView = <RenderProps,>({
|
||||||
data,
|
data,
|
||||||
@@ -58,6 +58,39 @@ export const TreeView = <RenderProps,>({
|
|||||||
setDraggingId(e.active.id as string);
|
setDraggingId(e.active.id as string);
|
||||||
}, []);
|
}, []);
|
||||||
if (enableDnd) {
|
if (enableDnd) {
|
||||||
|
const treeNodes = data.map((node, index) => (
|
||||||
|
<TreeNodeWithDnd
|
||||||
|
key={node.id}
|
||||||
|
index={index}
|
||||||
|
collapsedIds={collapsedIds}
|
||||||
|
setCollapsed={setCollapsed}
|
||||||
|
node={node}
|
||||||
|
selectedId={selectedId}
|
||||||
|
enableDnd={enableDnd}
|
||||||
|
disableCollapse={disableCollapse}
|
||||||
|
draggingId={draggingId}
|
||||||
|
{...otherProps}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
const draggingNode = (function () {
|
||||||
|
let draggingNode: Node<RenderProps> | undefined;
|
||||||
|
if (draggingId) {
|
||||||
|
draggingNode = findNode(draggingId, data);
|
||||||
|
}
|
||||||
|
if (draggingNode) {
|
||||||
|
return (
|
||||||
|
<TreeNode
|
||||||
|
node={draggingNode}
|
||||||
|
index={0}
|
||||||
|
allowDrop={false}
|
||||||
|
collapsedIds={collapsedIds}
|
||||||
|
setCollapsed={() => {}}
|
||||||
|
{...otherProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})();
|
||||||
return (
|
return (
|
||||||
<DndContext
|
<DndContext
|
||||||
sensors={sensors}
|
sensors={sensors}
|
||||||
@@ -65,33 +98,8 @@ export const TreeView = <RenderProps,>({
|
|||||||
onDragMove={onDragMove}
|
onDragMove={onDragMove}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
>
|
>
|
||||||
{data.map((node, index) => (
|
{treeNodes}
|
||||||
<TreeNodeWithDnd
|
<DragOverlay>{draggingNode}</DragOverlay>
|
||||||
key={node.id}
|
|
||||||
index={index}
|
|
||||||
collapsedIds={collapsedIds}
|
|
||||||
setCollapsed={setCollapsed}
|
|
||||||
node={node}
|
|
||||||
selectedId={selectedId}
|
|
||||||
enableDnd={enableDnd}
|
|
||||||
disableCollapse={disableCollapse}
|
|
||||||
draggingId={draggingId}
|
|
||||||
{...otherProps}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<DragOverlay>
|
|
||||||
{draggingId && (
|
|
||||||
<TreeNode
|
|
||||||
node={findNode(draggingId, data)!}
|
|
||||||
index={0}
|
|
||||||
allowDrop={false}
|
|
||||||
collapsedIds={collapsedIds}
|
|
||||||
setCollapsed={() => {}}
|
|
||||||
{...otherProps}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</DragOverlay>
|
|
||||||
</DndContext>
|
</DndContext>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,15 @@ export function useAffineListener(
|
|||||||
if (!fnRef.current) {
|
if (!fnRef.current) {
|
||||||
fnRef.current = listener;
|
fnRef.current = listener;
|
||||||
}
|
}
|
||||||
|
const ipcListener = fnRef.current ?? (fnRef.current = listener);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (once) {
|
if (once) {
|
||||||
window.affine.ipcRenderer.once(channel, fnRef.current!);
|
window.affine.ipcRenderer.once(channel, ipcListener);
|
||||||
} else {
|
} else {
|
||||||
window.affine.ipcRenderer.on(channel, fnRef.current!);
|
window.affine.ipcRenderer.on(channel, ipcListener);
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
window.affine.ipcRenderer.removeListener(channel, fnRef.current!);
|
window.affine.ipcRenderer.removeListener(channel, ipcListener);
|
||||||
};
|
};
|
||||||
}, [channel, once]);
|
}, [channel, once, ipcListener]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const createBroadCastChannelProvider = (
|
|||||||
case 'doc:diff': {
|
case 'doc:diff': {
|
||||||
const [, diff, clientId] = event.data;
|
const [, diff, clientId] = event.data;
|
||||||
const update = Y.encodeStateAsUpdate(doc, diff);
|
const update = Y.encodeStateAsUpdate(doc, diff);
|
||||||
broadcastChannel!.postMessage(['doc:update', update, clientId]);
|
broadcastChannel?.postMessage(['doc:update', update, clientId]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'doc:update': {
|
case 'doc:update': {
|
||||||
@@ -47,7 +47,7 @@ export const createBroadCastChannelProvider = (
|
|||||||
const [, clientId] = event.data;
|
const [, clientId] = event.data;
|
||||||
const clients = getClients(awareness);
|
const clients = getClients(awareness);
|
||||||
const update = encodeAwarenessUpdate(awareness, clients);
|
const update = encodeAwarenessUpdate(awareness, clients);
|
||||||
broadcastChannel!.postMessage(['awareness:update', update, clientId]);
|
broadcastChannel?.postMessage(['awareness:update', update, clientId]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'awareness:update': {
|
case 'awareness:update': {
|
||||||
|
|||||||
@@ -162,8 +162,7 @@ const sqliteOrigin = Symbol('sqlite-provider-origin');
|
|||||||
const createSQLiteProvider = (
|
const createSQLiteProvider = (
|
||||||
blockSuiteWorkspace: BlockSuiteWorkspace
|
blockSuiteWorkspace: BlockSuiteWorkspace
|
||||||
): SQLiteProvider => {
|
): SQLiteProvider => {
|
||||||
const apis = window.apis!;
|
const { apis, events } = window;
|
||||||
const events = window.events!;
|
|
||||||
// make sure it is being used in Electron with APIs
|
// make sure it is being used in Electron with APIs
|
||||||
assertExists(apis);
|
assertExists(apis);
|
||||||
assertExists(events);
|
assertExists(events);
|
||||||
@@ -216,7 +215,7 @@ const createSQLiteProvider = (
|
|||||||
const createSQLiteDBDownloadProvider = (
|
const createSQLiteDBDownloadProvider = (
|
||||||
blockSuiteWorkspace: BlockSuiteWorkspace
|
blockSuiteWorkspace: BlockSuiteWorkspace
|
||||||
): SQLiteDBDownloadProvider => {
|
): SQLiteDBDownloadProvider => {
|
||||||
const apis = window.apis!;
|
const { apis } = window;
|
||||||
let disconnected = false;
|
let disconnected = false;
|
||||||
|
|
||||||
let _resolve: () => void;
|
let _resolve: () => void;
|
||||||
@@ -273,7 +272,7 @@ const createSQLiteDBDownloadProvider = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.apis?.db.addBlob(
|
return apis?.db.addBlob(
|
||||||
blockSuiteWorkspace.id,
|
blockSuiteWorkspace.id,
|
||||||
k,
|
k,
|
||||||
new Uint8Array(await blob.arrayBuffer())
|
new Uint8Array(await blob.arrayBuffer())
|
||||||
|
|||||||
@@ -65,9 +65,10 @@ export function createEmptyBlockSuiteWorkspace(
|
|||||||
const blobStorages: StoreOptions['blobStorages'] = [];
|
const blobStorages: StoreOptions['blobStorages'] = [];
|
||||||
|
|
||||||
if (flavour === WorkspaceFlavour.AFFINE) {
|
if (flavour === WorkspaceFlavour.AFFINE) {
|
||||||
blobStorages.push(id =>
|
if (config && config.workspaceApis) {
|
||||||
createAffineBlobStorage(id, config!.workspaceApis!)
|
const workspaceApis = config.workspaceApis;
|
||||||
);
|
blobStorages.push(id => createAffineBlobStorage(id, workspaceApis));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
blobStorages.push(createIndexeddbStorage);
|
blobStorages.push(createIndexeddbStorage);
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ const handleEnter = ({
|
|||||||
null
|
null
|
||||||
>;
|
>;
|
||||||
const vEditor = getVirgoByModel(blockRange.models[0]);
|
const vEditor = getVirgoByModel(blockRange.models[0]);
|
||||||
const linkInfo = vEditor!
|
const linkInfo = vEditor
|
||||||
.getDeltasByVRange({
|
?.getDeltasByVRange({
|
||||||
index: blockRange.startOffset,
|
index: blockRange.startOffset,
|
||||||
length: 0,
|
length: 0,
|
||||||
})
|
})
|
||||||
@@ -70,7 +70,7 @@ const handleEnter = ({
|
|||||||
currentBlockIndex + 1
|
currentBlockIndex + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
vEditor!.deleteText({
|
vEditor?.deleteText({
|
||||||
index,
|
index,
|
||||||
length,
|
length,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true
|
||||||
|
},
|
||||||
|
"include": ["."],
|
||||||
|
"exclude": [
|
||||||
|
"target",
|
||||||
|
"node_modules",
|
||||||
|
"dist",
|
||||||
|
"lib",
|
||||||
|
".coverage",
|
||||||
|
".yarn",
|
||||||
|
"test-results"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user