mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-22 12:36:24 +08:00
Merge remote-tracking branch 'origin/develop' into feature/new-grid-drop
This commit is contained in:
@@ -36,6 +36,9 @@ export class GridBlock extends BaseView {
|
||||
}
|
||||
return block.remove();
|
||||
}
|
||||
if (block.childrenIds.length === 0) {
|
||||
return block.remove();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,13 @@ export const CardContainer = (props: CardContainerProps) => {
|
||||
const { kanban } = useKanban();
|
||||
const { containerIds, items: dataSource, activeId } = props;
|
||||
return (
|
||||
<KanbanContainer>
|
||||
<KanbanContainer
|
||||
onMouseDown={e => {
|
||||
// Fix https://github.com/toeverything/AFFiNE/issues/29
|
||||
// Prevent active selection when dragging kanban card
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{containerIds.map((containerId, idx) => {
|
||||
const items = dataSource[containerId];
|
||||
|
||||
|
||||
@@ -128,8 +128,12 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
||||
if (clientHeight - rectTop <= COMMAND_MENU_HEIGHT) {
|
||||
setCommandMenuPosition({
|
||||
left: rect.left - left,
|
||||
bottom: rectTop - top + 10,
|
||||
top: 'initial',
|
||||
top:
|
||||
rectTop -
|
||||
top -
|
||||
COMMAND_MENU_HEIGHT +
|
||||
20,
|
||||
bottom: 'initial',
|
||||
});
|
||||
} else {
|
||||
setCommandMenuPosition({
|
||||
|
||||
@@ -17,16 +17,20 @@ export const StatusIcon = ({ mode }: StatusIconProps) => {
|
||||
const IconWrapper = styled('div')<Pick<StatusIconProps, 'mode'>>(
|
||||
({ theme, mode }) => {
|
||||
return {
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '5px',
|
||||
boxShadow: theme.affine.shadows.shadow1,
|
||||
color: theme.affine.palette.primary,
|
||||
cursor: 'pointer',
|
||||
backgroundColor: theme.affine.palette.white,
|
||||
transform: `translateX(${mode === DocMode.doc ? 0 : 20}px)`,
|
||||
transform: `translateX(${mode === DocMode.doc ? 0 : 30}px)`,
|
||||
transition: 'transform 300ms ease',
|
||||
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
|
||||
'& > svg': {
|
||||
fontSize: '20px',
|
||||
},
|
||||
|
||||
@@ -2,26 +2,37 @@ import { styled } from '@toeverything/components/ui';
|
||||
|
||||
type StatusTextProps = {
|
||||
children: string;
|
||||
width?: string;
|
||||
active?: boolean;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const StatusText = ({ children, active, onClick }: StatusTextProps) => {
|
||||
export const StatusText = ({
|
||||
children,
|
||||
width,
|
||||
active,
|
||||
onClick,
|
||||
}: StatusTextProps) => {
|
||||
return (
|
||||
<StyledText active={active} onClick={onClick}>
|
||||
<StyledText width={width} active={active} onClick={onClick}>
|
||||
{children}
|
||||
</StyledText>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledText = styled('div')<StatusTextProps>(({ theme, active }) => {
|
||||
return {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: theme.affine.palette.primary,
|
||||
fontWeight: active ? '500' : '300',
|
||||
fontSize: '15px',
|
||||
cursor: 'pointer',
|
||||
padding: '0 6px',
|
||||
};
|
||||
});
|
||||
const StyledText = styled('div')<StatusTextProps>(
|
||||
({ theme, width, active }) => {
|
||||
return {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: active
|
||||
? theme.affine.palette.primary
|
||||
: 'rgba(62, 111, 219, 0.6)',
|
||||
fontWeight: active ? '600' : '400',
|
||||
fontSize: '16px',
|
||||
lineHeight: '22px',
|
||||
cursor: 'pointer',
|
||||
...(!!width && { width }),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -18,11 +18,15 @@ export const StatusTrack: FC<StatusTrackProps> = ({ mode, onClick }) => {
|
||||
|
||||
const Container = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '64px',
|
||||
height: '32px',
|
||||
backgroundColor: theme.affine.palette.textHover,
|
||||
borderRadius: '5px',
|
||||
height: '30px',
|
||||
width: '50px',
|
||||
border: '1px solid #ECF1FB',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
padding: '5px',
|
||||
margin: '0 8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0 4px',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -32,6 +32,7 @@ export const Switcher = () => {
|
||||
return (
|
||||
<StyledContainerForSwitcher>
|
||||
<StatusText
|
||||
width={'44px'}
|
||||
active={pageViewMode === DocMode.doc}
|
||||
onClick={() => switchToPageView(DocMode.doc)}
|
||||
>
|
||||
@@ -48,6 +49,7 @@ export const Switcher = () => {
|
||||
}}
|
||||
/>
|
||||
<StatusText
|
||||
width={'56px'}
|
||||
active={pageViewMode === DocMode.board}
|
||||
onClick={() => switchToPageView(DocMode.board)}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconButton, styled } from '@toeverything/components/ui';
|
||||
import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
|
||||
import {
|
||||
LogoIcon,
|
||||
SideBarViewIcon,
|
||||
@@ -24,9 +24,13 @@ export const LayoutHeader = () => {
|
||||
</FlexContainer>
|
||||
<FlexContainer>
|
||||
<StyledHelper>
|
||||
<StyledShare>Share</StyledShare>
|
||||
<StyledShare disabled={true}>Share</StyledShare>
|
||||
<div style={{ margin: '0px 12px' }}>
|
||||
<IconButton size="large">
|
||||
<IconButton
|
||||
size="large"
|
||||
hoverColor={'transparent'}
|
||||
disabled={true}
|
||||
>
|
||||
<SearchIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
@@ -119,17 +123,19 @@ const StyledHelper = styled('div')({
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
const StyledShare = styled('div')({
|
||||
const StyledShare = styled(MuiButton)<{ disabled?: boolean }>({
|
||||
padding: '10px 12px',
|
||||
fontWeight: 600,
|
||||
fontSize: '14px',
|
||||
color: '#3E6FDB',
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:hover': {
|
||||
background: '#F5F7F8',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
color: '#98ACBD',
|
||||
textTransform: 'none',
|
||||
/* disabled for current time */
|
||||
// color: '#3E6FDB',
|
||||
// '&:hover': {
|
||||
// background: '#F5F7F8',
|
||||
// borderRadius: '5px',
|
||||
// },
|
||||
});
|
||||
|
||||
const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
|
||||
@@ -141,9 +147,7 @@ const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
|
||||
|
||||
const StyledContainerForEditorBoardSwitcher = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
left: '50%',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -67,8 +67,12 @@ export function ChildrenListenerHandler(
|
||||
const keys = Array.from(event.keys.entries()).map(
|
||||
([key, { action }]) => [key, action] as [string, ChangedStateKeys]
|
||||
);
|
||||
const deleted = Array.from(event.changes.deleted.values())
|
||||
.flatMap(val => val.content.getContent() as string[])
|
||||
.filter(v => v)
|
||||
.map(k => [k, 'delete'] as [string, ChangedStateKeys]);
|
||||
for (const listener of listeners.values()) {
|
||||
EmitEvents(keys, listener);
|
||||
EmitEvents([...keys, ...deleted], listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,13 @@ export class AbstractBlock<
|
||||
C extends ContentOperation
|
||||
> {
|
||||
private readonly _id: string;
|
||||
readonly #block: BlockInstance<C>;
|
||||
private readonly _block: BlockInstance<C>;
|
||||
private readonly _history: HistoryManager;
|
||||
private readonly _root?: AbstractBlock<B, C>;
|
||||
private readonly _parentListener: Map<string, BlockListener>;
|
||||
|
||||
_parent?: AbstractBlock<B, C>;
|
||||
private _parent?: AbstractBlock<B, C>;
|
||||
private _changeParent?: () => void;
|
||||
|
||||
constructor(
|
||||
block: B,
|
||||
@@ -40,20 +41,14 @@ export class AbstractBlock<
|
||||
parent?: AbstractBlock<B, C>
|
||||
) {
|
||||
this._id = block.id;
|
||||
this.#block = block;
|
||||
this._history = this.#block.scopedHistory([this._id]);
|
||||
this._block = block;
|
||||
this._history = this._block.scopedHistory([this._id]);
|
||||
|
||||
this._root = root;
|
||||
this._parentListener = new Map();
|
||||
this._parent = parent;
|
||||
|
||||
JWT_DEV && logger_debug(`init: exists ${this._id}`);
|
||||
if (parent) {
|
||||
parent.addChildrenListener(this._id, states => {
|
||||
if (states.get(this._id) === 'delete') {
|
||||
this._emitParent(parent._id, 'delete');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (parent) this._refreshParent(parent);
|
||||
}
|
||||
|
||||
public get root() {
|
||||
@@ -66,7 +61,7 @@ export class AbstractBlock<
|
||||
|
||||
protected _getParentPage(warning = true): string | undefined {
|
||||
if (this.flavor === 'page') {
|
||||
return this.#block.id;
|
||||
return this._block.id;
|
||||
} else if (!this._parent) {
|
||||
if (warning && this.flavor !== 'workspace') {
|
||||
console.warn('parent not found');
|
||||
@@ -89,7 +84,7 @@ export class AbstractBlock<
|
||||
if (event === 'parent') {
|
||||
this._parentListener.set(name, callback);
|
||||
} else {
|
||||
this.#block.on(event, name, callback);
|
||||
this._block.on(event, name, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,42 +92,40 @@ export class AbstractBlock<
|
||||
if (event === 'parent') {
|
||||
this._parentListener.delete(name);
|
||||
} else {
|
||||
this.#block.off(event, name);
|
||||
this._block.off(event, name);
|
||||
}
|
||||
}
|
||||
|
||||
public addChildrenListener(name: string, listener: BlockListener) {
|
||||
this.#block.addChildrenListener(name, listener);
|
||||
this._block.addChildrenListener(name, listener);
|
||||
}
|
||||
|
||||
public removeChildrenListener(name: string) {
|
||||
this.#block.removeChildrenListener(name);
|
||||
this._block.removeChildrenListener(name);
|
||||
}
|
||||
|
||||
public addContentListener(name: string, listener: BlockListener) {
|
||||
this.#block.addContentListener(name, listener);
|
||||
this._block.addContentListener(name, listener);
|
||||
}
|
||||
|
||||
public removeContentListener(name: string) {
|
||||
this.#block.removeContentListener(name);
|
||||
this._block.removeContentListener(name);
|
||||
}
|
||||
|
||||
public getContent<
|
||||
T extends ContentTypes = ContentOperation
|
||||
>(): MapOperation<T> {
|
||||
if (this.#block.type === BlockTypes.block) {
|
||||
return this.#block.content.asMap() as MapOperation<T>;
|
||||
if (this._block.type === BlockTypes.block) {
|
||||
return this._block.content.asMap() as MapOperation<T>;
|
||||
}
|
||||
throw new Error(
|
||||
`this block not a structured block: ${this._id}, ${
|
||||
this.#block.type
|
||||
}`
|
||||
`this block not a structured block: ${this._id}, ${this._block.type}`
|
||||
);
|
||||
}
|
||||
|
||||
public getBinary(): ArrayBuffer | undefined {
|
||||
if (this.#block.type === BlockTypes.binary) {
|
||||
return this.#block.content.asArray<ArrayBuffer>()?.get(0);
|
||||
if (this._block.type === BlockTypes.binary) {
|
||||
return this._block.content.asArray<ArrayBuffer>()?.get(0);
|
||||
}
|
||||
throw new Error('this block not a binary block');
|
||||
}
|
||||
@@ -162,7 +155,7 @@ export class AbstractBlock<
|
||||
|
||||
// Last update UTC time
|
||||
public get lastUpdated(): number {
|
||||
return this.#block.updated || this.#block.created;
|
||||
return this._block.updated || this._block.created;
|
||||
}
|
||||
|
||||
private get last_updated_date(): string | undefined {
|
||||
@@ -171,7 +164,7 @@ export class AbstractBlock<
|
||||
|
||||
// create UTC time
|
||||
public get created(): number {
|
||||
return this.#block.created;
|
||||
return this._block.created;
|
||||
}
|
||||
|
||||
private get created_date(): string | undefined {
|
||||
@@ -180,11 +173,11 @@ export class AbstractBlock<
|
||||
|
||||
// creator id
|
||||
public get creator(): string | undefined {
|
||||
return this.#block.creator;
|
||||
return this._block.creator;
|
||||
}
|
||||
|
||||
[_GET_BLOCK]() {
|
||||
return this.#block;
|
||||
return this._block;
|
||||
}
|
||||
|
||||
private _emitParent(
|
||||
@@ -199,8 +192,20 @@ export class AbstractBlock<
|
||||
}
|
||||
}
|
||||
|
||||
[_SET_PARENT](parent: AbstractBlock<B, C>) {
|
||||
private _refreshParent(parent: AbstractBlock<B, C>) {
|
||||
this._changeParent?.();
|
||||
parent.addChildrenListener(this._id, states => {
|
||||
if (states.get(this._id) === 'delete') {
|
||||
this._emitParent(parent._id, 'delete');
|
||||
}
|
||||
});
|
||||
|
||||
this._parent = parent;
|
||||
this._changeParent = () => parent.removeChildrenListener(this._id);
|
||||
}
|
||||
|
||||
[_SET_PARENT](parent: AbstractBlock<B, C>) {
|
||||
this._refreshParent(parent);
|
||||
this._emitParent(parent.id);
|
||||
}
|
||||
|
||||
@@ -234,23 +239,23 @@ export class AbstractBlock<
|
||||
* current block type
|
||||
*/
|
||||
public get type(): typeof BlockTypes[BlockTypeKeys] {
|
||||
return this.#block.type;
|
||||
return this._block.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* current block flavor
|
||||
*/
|
||||
public get flavor(): typeof BlockFlavors[BlockFlavorKeys] {
|
||||
return this.#block.flavor;
|
||||
return this._block.flavor;
|
||||
}
|
||||
|
||||
// TODO: flavor needs optimization
|
||||
setFlavor(flavor: typeof BlockFlavors[BlockFlavorKeys]) {
|
||||
this.#block.setFlavor(flavor);
|
||||
this._block.setFlavor(flavor);
|
||||
}
|
||||
|
||||
public get children(): string[] {
|
||||
return this.#block.children;
|
||||
return this._block.children;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,12 +279,12 @@ export class AbstractBlock<
|
||||
throw new Error('insertChildren: binary not allow insert children');
|
||||
}
|
||||
|
||||
this.#block.insertChildren(block[_GET_BLOCK](), position);
|
||||
this._block.insertChildren(block[_GET_BLOCK](), position);
|
||||
block[_SET_PARENT](this);
|
||||
}
|
||||
|
||||
public hasChildren(id: string): boolean {
|
||||
return this.#block.hasChildren(id);
|
||||
return this._block.hasChildren(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,11 +294,11 @@ export class AbstractBlock<
|
||||
*/
|
||||
protected get_children(blockId?: string): BlockInstance<C>[] {
|
||||
JWT_DEV && logger(`get children: ${blockId}`);
|
||||
return this.#block.getChildren([blockId]);
|
||||
return this._block.getChildren([blockId]);
|
||||
}
|
||||
|
||||
public removeChildren(blockId?: string) {
|
||||
this.#block.removeChildren([blockId]);
|
||||
this._block.removeChildren([blockId]);
|
||||
}
|
||||
|
||||
public remove() {
|
||||
|
||||
Reference in New Issue
Block a user