mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-18 02:26:21 +08:00
Bugfix/board style (#321)
* fix style * fix drag bounds * fix drag bounds * delete log * delete log * fix:lint * fix:lint * fix:lint * fix:bounds show
This commit is contained in:
@@ -51,11 +51,10 @@ const AffineBoard = ({
|
||||
};
|
||||
});
|
||||
|
||||
const { shapes, bindings } = useShapes(workspace, rootBlockId);
|
||||
|
||||
const { shapes } = useShapes(workspace, rootBlockId);
|
||||
useEffect(() => {
|
||||
if (app) {
|
||||
app.replacePageContent(shapes || {}, bindings, {});
|
||||
app.replacePageContent(shapes || {}, {}, {});
|
||||
}
|
||||
}, [app, shapes]);
|
||||
|
||||
@@ -69,7 +68,9 @@ const AffineBoard = ({
|
||||
onMount(app) {
|
||||
set_app(app);
|
||||
},
|
||||
|
||||
async onPaste(e, data) {
|
||||
console.log('e,data: ', e, data);
|
||||
},
|
||||
async onCopy(e, groupIds) {
|
||||
const clip = await getClipDataOfBlocksById(
|
||||
editor,
|
||||
@@ -110,18 +111,6 @@ const AffineBoard = ({
|
||||
});
|
||||
}
|
||||
shape.affineId = block.id;
|
||||
Object.keys(bindings).forEach(bilingKey => {
|
||||
if (
|
||||
bindings[bilingKey]?.fromId === shape.id
|
||||
) {
|
||||
bindings[bilingKey].fromId = block.id;
|
||||
}
|
||||
if (
|
||||
bindings[bilingKey]?.toId === shape.id
|
||||
) {
|
||||
bindings[bilingKey].toId = block.id;
|
||||
}
|
||||
});
|
||||
return await services.api.editorBlock.update({
|
||||
workspace: shape.workspace,
|
||||
id: block.id,
|
||||
@@ -134,30 +123,6 @@ const AffineBoard = ({
|
||||
}
|
||||
})
|
||||
);
|
||||
const pageBindingsString = (
|
||||
await services.api.editorBlock.get({
|
||||
workspace: workspace,
|
||||
ids: [rootBlockId],
|
||||
})
|
||||
)?.[0].properties.bindings?.value;
|
||||
const pageBindings = JSON.parse(pageBindingsString ?? '{}');
|
||||
Object.keys(bindings).forEach(bindingsKey => {
|
||||
if (!bindings[bindingsKey]) {
|
||||
delete pageBindings[bindingsKey];
|
||||
} else {
|
||||
Object.assign(pageBindings, bindings);
|
||||
}
|
||||
});
|
||||
|
||||
await services.api.editorBlock.update({
|
||||
workspace: workspace,
|
||||
id: rootBlockId,
|
||||
properties: {
|
||||
bindings: {
|
||||
value: JSON.stringify(pageBindings),
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -5,24 +5,12 @@ import { services } from '@toeverything/datasource/db-service';
|
||||
import { usePageClientWidth } from '@toeverything/datasource/state';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const getBindings = (workspace: string, rootBlockId: string) => {
|
||||
return services.api.editorBlock
|
||||
.get({
|
||||
workspace: workspace,
|
||||
ids: [rootBlockId],
|
||||
})
|
||||
.then(blcoks => {
|
||||
return blcoks[0]?.properties.bindings?.value;
|
||||
});
|
||||
};
|
||||
|
||||
export const useShapes = (workspace: string, rootBlockId: string) => {
|
||||
const { pageClientWidth } = usePageClientWidth();
|
||||
// page padding left and right total 300px
|
||||
const editorShapeInitSize = pageClientWidth - 300;
|
||||
const [blocks, setBlocks] = useState<{
|
||||
shapes: [ReturnEditorBlock[]];
|
||||
bindings: string;
|
||||
}>();
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
@@ -43,11 +31,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
|
||||
return shapes;
|
||||
}),
|
||||
]).then(shapes => {
|
||||
getBindings(workspace, rootBlockId).then(bindings => {
|
||||
setBlocks({
|
||||
shapes,
|
||||
bindings: bindings,
|
||||
});
|
||||
setBlocks({
|
||||
shapes: shapes,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -65,11 +50,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
|
||||
return childBlock;
|
||||
})
|
||||
).then(shapes => {
|
||||
getBindings(workspace, rootBlockId).then(bindings => {
|
||||
setBlocks({
|
||||
shapes: [shapes],
|
||||
bindings: bindings,
|
||||
});
|
||||
setBlocks({
|
||||
shapes: [shapes],
|
||||
});
|
||||
});
|
||||
})
|
||||
@@ -107,6 +89,5 @@ export const useShapes = (workspace: string, rootBlockId: string) => {
|
||||
|
||||
return {
|
||||
shapes: blocksShapes,
|
||||
bindings: JSON.parse(blocks?.bindings ?? '{}'),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -362,7 +362,7 @@ const InnerTldraw = memo(function InnerTldraw({
|
||||
|
||||
// Hide bounds when not using the select tool, or when the only selected shape has handles
|
||||
const hideBounds =
|
||||
(isInSession && app.session?.constructor.name !== 'BrushSession') ||
|
||||
(isInSession && app.session?.constructor.name === 'BrushSession') ||
|
||||
!isSelecting ||
|
||||
isHideBoundsShape ||
|
||||
!!pageState.editingId;
|
||||
|
||||
@@ -56,7 +56,8 @@ const SelectableContainer = styled('div')<{ selected?: boolean }>(
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
margin: '5px',
|
||||
padding: '3px',
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
cursor: 'pointer',
|
||||
boxSizing: 'border-box',
|
||||
'&:hover': {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { TLDR, TldrawApp } from '@toeverything/components/board-state';
|
||||
import { Divider, Popover, styled } from '@toeverything/components/ui';
|
||||
import { Fragment } from 'react';
|
||||
import { AlignOperation } from './AlignOperation';
|
||||
import { ArrowTo } from './ArrowTo';
|
||||
import { BorderColorConfig } from './BorderColorConfig';
|
||||
import { DeleteShapes } from './DeleteOperation';
|
||||
import { FillColorConfig } from './FillColorConfig';
|
||||
@@ -107,12 +106,12 @@ export const CommandPanel = ({ app }: { app: TldrawApp }) => {
|
||||
shapes={config.deleteShapes.selectedShapes}
|
||||
></AlignOperation>
|
||||
) : null,
|
||||
toNextShap: (
|
||||
<ArrowTo
|
||||
app={app}
|
||||
shapes={config.deleteShapes.selectedShapes}
|
||||
></ArrowTo>
|
||||
),
|
||||
// toNextShap: (
|
||||
// <ArrowTo
|
||||
// app={app}
|
||||
// shapes={config.deleteShapes.selectedShapes}
|
||||
// ></ArrowTo>
|
||||
// ),
|
||||
};
|
||||
|
||||
const nodes = Object.entries(configNodes).filter(([key, node]) => !!node);
|
||||
|
||||
@@ -42,7 +42,7 @@ type E = HTMLDivElement;
|
||||
export class ArrowUtil extends TDShapeUtil<T, E> {
|
||||
type = TDShapeType.Arrow as const;
|
||||
|
||||
override hideBounds = true;
|
||||
override hideBounds = false;
|
||||
|
||||
override canEdit = true;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Utils } from '@tldraw/core';
|
||||
import type { ShapeStyles } from '@toeverything/components/board-types';
|
||||
import { BINDING_DISTANCE } from '@toeverything/components/board-types';
|
||||
import {
|
||||
BINDING_DISTANCE,
|
||||
ShapeStyles,
|
||||
} from '@toeverything/components/board-types';
|
||||
import * as React from 'react';
|
||||
import { getShapeStyle } from '../../shared';
|
||||
|
||||
@@ -56,23 +58,20 @@ export const DashedRectangle = React.memo(function DashedRectangle({
|
||||
return (
|
||||
<>
|
||||
<rect
|
||||
className={
|
||||
isSelected || style.isFilled
|
||||
? 'tl-fill-hitarea'
|
||||
: 'tl-stroke-hitarea'
|
||||
}
|
||||
className={'tl-fill-hitarea'}
|
||||
x={sw / 2}
|
||||
y={sw / 2}
|
||||
width={w}
|
||||
height={h}
|
||||
opacity={1}
|
||||
strokeWidth={BINDING_DISTANCE}
|
||||
/>
|
||||
{style.isFilled && (
|
||||
<rect
|
||||
x={sw / 2}
|
||||
y={sw / 2}
|
||||
width={w}
|
||||
height={h}
|
||||
width={w - sw / 2}
|
||||
height={h - sw / 2}
|
||||
fill={fill}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
|
||||
@@ -175,6 +175,10 @@ interface TDCallbacks {
|
||||
* (optional) A callback to run when the shape is copied.
|
||||
*/
|
||||
onCopy?: (e: ClipboardEvent, ids: string[]) => void;
|
||||
/**
|
||||
* (optional) A callback to run when the shape is paste.
|
||||
*/
|
||||
onPaste?: (e: ClipboardEvent, data: any) => void;
|
||||
}
|
||||
|
||||
export interface TldrawAppCtorProps {
|
||||
@@ -1956,6 +1960,53 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||
paste = async (point?: number[], e?: ClipboardEvent) => {
|
||||
if (this.readOnly) return;
|
||||
|
||||
if (e) {
|
||||
const data = e.clipboardData?.getData('text/html');
|
||||
const paste_as_html = (html: string) => {
|
||||
try {
|
||||
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
|
||||
|
||||
if (!maybeJson) return;
|
||||
|
||||
const json: {
|
||||
type: string;
|
||||
shapes: TDShape[];
|
||||
bindings: TDBinding[];
|
||||
assets: TDAsset[];
|
||||
} = JSON.parse(maybeJson);
|
||||
return json;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
this.callbacks.onPaste?.(e, paste_as_html(data));
|
||||
return this;
|
||||
}
|
||||
|
||||
const paste_as_html = (html: string) => {
|
||||
try {
|
||||
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
|
||||
|
||||
if (!maybeJson) return;
|
||||
|
||||
const json: {
|
||||
type: string;
|
||||
shapes: TDShape[];
|
||||
bindings: TDBinding[];
|
||||
assets: TDAsset[];
|
||||
} = JSON.parse(maybeJson);
|
||||
|
||||
if (json.type === 'tldr/clipboard') {
|
||||
pasteInCurrentPage(json.shapes, json.bindings, json.assets);
|
||||
return;
|
||||
} else {
|
||||
throw Error('Not tldraw data!');
|
||||
}
|
||||
} catch (e) {
|
||||
pasteTextAsShape(html);
|
||||
return;
|
||||
}
|
||||
};
|
||||
const pasteInCurrentPage = (
|
||||
shapes: TDShape[],
|
||||
bindings: TDBinding[],
|
||||
@@ -2107,31 +2158,6 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||
// this.select(shapeId);
|
||||
};
|
||||
|
||||
const paste_as_html = (html: string) => {
|
||||
try {
|
||||
const maybeJson = html.match(/<tldraw>(.*)<\/tldraw>/)?.[1];
|
||||
|
||||
if (!maybeJson) return;
|
||||
|
||||
const json: {
|
||||
type: string;
|
||||
shapes: TDShape[];
|
||||
bindings: TDBinding[];
|
||||
assets: TDAsset[];
|
||||
} = JSON.parse(maybeJson);
|
||||
|
||||
if (json.type === 'tldr/clipboard') {
|
||||
pasteInCurrentPage(json.shapes, json.bindings, json.assets);
|
||||
return;
|
||||
} else {
|
||||
throw Error('Not tldraw data!');
|
||||
}
|
||||
} catch (e) {
|
||||
pasteTextAsShape(html);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if (e !== undefined) {
|
||||
const items: DataTransferItemList =
|
||||
e.clipboardData?.items ?? ({} as DataTransferItemList);
|
||||
|
||||
@@ -1,58 +1,54 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { StyleWithAtRules } from 'style9';
|
||||
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import { sql, MySQL, PostgreSQL } from '@codemirror/lang-sql';
|
||||
import { java } from '@codemirror/lang-java';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
import { cpp } from '@codemirror/lang-cpp';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { java } from '@codemirror/lang-java';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { lezer } from '@codemirror/lang-lezer';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { php } from '@codemirror/lang-php';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
import { MySQL, PostgreSQL, sql } from '@codemirror/lang-sql';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import { StreamLanguage } from '@codemirror/language';
|
||||
import { go } from '@codemirror/legacy-modes/mode/go';
|
||||
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
|
||||
import { shell } from '@codemirror/legacy-modes/mode/shell';
|
||||
import { lua } from '@codemirror/legacy-modes/mode/lua';
|
||||
import { swift } from '@codemirror/legacy-modes/mode/swift';
|
||||
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
|
||||
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
|
||||
import { vb } from '@codemirror/legacy-modes/mode/vb';
|
||||
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
|
||||
import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck';
|
||||
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
|
||||
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
|
||||
import { elixir } from 'codemirror-lang-elixir';
|
||||
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
|
||||
import { perl } from '@codemirror/legacy-modes/mode/perl';
|
||||
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
|
||||
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
|
||||
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
|
||||
import { toml } from '@codemirror/legacy-modes/mode/toml';
|
||||
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
|
||||
import { clojure } from '@codemirror/legacy-modes/mode/clojure';
|
||||
import { coffeeScript } from '@codemirror/legacy-modes/mode/coffeescript';
|
||||
import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile';
|
||||
import { erlang } from '@codemirror/legacy-modes/mode/erlang';
|
||||
import { go } from '@codemirror/legacy-modes/mode/go';
|
||||
import { julia } from '@codemirror/legacy-modes/mode/julia';
|
||||
import { liveScript } from '@codemirror/legacy-modes/mode/livescript';
|
||||
import { lua } from '@codemirror/legacy-modes/mode/lua';
|
||||
import { nginx } from '@codemirror/legacy-modes/mode/nginx';
|
||||
import { pascal } from '@codemirror/legacy-modes/mode/pascal';
|
||||
import { perl } from '@codemirror/legacy-modes/mode/perl';
|
||||
import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
|
||||
import { r } from '@codemirror/legacy-modes/mode/r';
|
||||
import { ruby } from '@codemirror/legacy-modes/mode/ruby';
|
||||
import { scheme } from '@codemirror/legacy-modes/mode/scheme';
|
||||
import { shell } from '@codemirror/legacy-modes/mode/shell';
|
||||
import { stylus } from '@codemirror/legacy-modes/mode/stylus';
|
||||
import { swift } from '@codemirror/legacy-modes/mode/swift';
|
||||
import { tcl } from '@codemirror/legacy-modes/mode/tcl';
|
||||
import { toml } from '@codemirror/legacy-modes/mode/toml';
|
||||
import { vb } from '@codemirror/legacy-modes/mode/vb';
|
||||
import { vbScript } from '@codemirror/legacy-modes/mode/vbscript';
|
||||
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
|
||||
import { Extension } from '@codemirror/state';
|
||||
import { Option, Select } from '@toeverything/components/ui';
|
||||
|
||||
import {
|
||||
useOnSelect,
|
||||
BlockPendantProvider,
|
||||
useOnSelect,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import { DuplicateIcon } from '@toeverything/components/icons';
|
||||
import { Option, Select, styled } from '@toeverything/components/ui';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { copyToClipboard } from '@toeverything/utils';
|
||||
import { elixir } from 'codemirror-lang-elixir';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { StyleWithAtRules } from 'style9';
|
||||
import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
|
||||
|
||||
interface CreateCodeView extends CreateView {
|
||||
style9?: StyleWithAtRules;
|
||||
@@ -110,13 +106,15 @@ const CodeBlock = styled('div')(({ theme }) => ({
|
||||
borderRadius: theme.affine.shape.borderRadius,
|
||||
'&:hover': {
|
||||
'.operation': {
|
||||
display: 'flex',
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
'.operation': {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between',
|
||||
opacity: 0,
|
||||
transition: 'opacity 1.5s',
|
||||
},
|
||||
'.copy-block': {
|
||||
padding: '0px 10px',
|
||||
|
||||
Reference in New Issue
Block a user