mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-09 13:15:51 +08:00
chore: bump toolchain & fix lint
This commit is contained in:
@@ -117,7 +117,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
|
|||||||
|
|
||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
const {
|
const {
|
||||||
title = 'GitHub',
|
title,
|
||||||
githubType,
|
githubType,
|
||||||
status,
|
status,
|
||||||
statusReason,
|
statusReason,
|
||||||
@@ -139,7 +139,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
|
|||||||
? getGithubStatusIcon(githubType, status, statusReason)
|
? getGithubStatusIcon(githubType, status, statusReason)
|
||||||
: nothing;
|
: nothing;
|
||||||
const statusText = loading ? '' : status;
|
const statusText = loading ? '' : status;
|
||||||
const titleText = loading ? 'Loading...' : title;
|
const titleText = loading ? 'Loading...' : title || 'GitHub';
|
||||||
const descriptionText = loading ? '' : description;
|
const descriptionText = loading ? '' : description;
|
||||||
const bannerImage =
|
const bannerImage =
|
||||||
!loading && image
|
!loading && image
|
||||||
|
|||||||
@@ -89,14 +89,14 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
const { image, title = 'Loom', description, videoId } = this.model.props;
|
const { image, title, description, videoId } = this.model.props;
|
||||||
|
|
||||||
const loading = this.loading;
|
const loading = this.loading;
|
||||||
const theme = this.std.get(ThemeProvider).theme;
|
const theme = this.std.get(ThemeProvider).theme;
|
||||||
const imageProxyService = this.store.get(ImageProxyService);
|
const imageProxyService = this.store.get(ImageProxyService);
|
||||||
const { EmbedCardBannerIcon } = getEmbedCardIcons(theme);
|
const { EmbedCardBannerIcon } = getEmbedCardIcons(theme);
|
||||||
const titleIcon = loading ? LoadingIcon() : LoomIcon;
|
const titleIcon = loading ? LoadingIcon() : LoomIcon;
|
||||||
const titleText = loading ? 'Loading...' : title;
|
const titleText = loading ? 'Loading...' : title || 'Loom';
|
||||||
const descriptionText = loading ? '' : description;
|
const descriptionText = loading ? '' : description;
|
||||||
const bannerImage =
|
const bannerImage =
|
||||||
!loading && image
|
!loading && image
|
||||||
|
|||||||
@@ -96,21 +96,15 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
const {
|
const { image, title, description, creator, creatorImage, videoId } =
|
||||||
image,
|
this.model.props;
|
||||||
title = 'YouTube',
|
|
||||||
description,
|
|
||||||
creator,
|
|
||||||
creatorImage,
|
|
||||||
videoId,
|
|
||||||
} = this.model.props;
|
|
||||||
|
|
||||||
const loading = this.loading;
|
const loading = this.loading;
|
||||||
const theme = this.std.get(ThemeProvider).theme;
|
const theme = this.std.get(ThemeProvider).theme;
|
||||||
const imageProxyService = this.store.get(ImageProxyService);
|
const imageProxyService = this.store.get(ImageProxyService);
|
||||||
const { EmbedCardBannerIcon } = getEmbedCardIcons(theme);
|
const { EmbedCardBannerIcon } = getEmbedCardIcons(theme);
|
||||||
const titleIcon = loading ? LoadingIcon() : YoutubeIcon;
|
const titleIcon = loading ? LoadingIcon() : YoutubeIcon;
|
||||||
const titleText = loading ? 'Loading...' : title;
|
const titleText = loading ? 'Loading...' : title || 'YouTube';
|
||||||
const descriptionText = loading ? null : description;
|
const descriptionText = loading ? null : description;
|
||||||
const bannerImage =
|
const bannerImage =
|
||||||
!loading && image
|
!loading && image
|
||||||
|
|||||||
@@ -276,7 +276,8 @@ export class ImageEdgelessBlockComponent extends GfxBlockComponent<ImageBlockMod
|
|||||||
|
|
||||||
override renderGfxBlock() {
|
override renderGfxBlock() {
|
||||||
const blobUrl = this.blobUrl;
|
const blobUrl = this.blobUrl;
|
||||||
const { rotate = 0, size = 0, caption = 'Image' } = this.model.props;
|
const { rotate, size: rawSize, caption = 'Image' } = this.model.props;
|
||||||
|
const size = rawSize ?? 0;
|
||||||
this._resetLodSource(blobUrl);
|
this._resetLodSource(blobUrl);
|
||||||
|
|
||||||
const containerStyleMap = styleMap({
|
const containerStyleMap = styleMap({
|
||||||
|
|||||||
@@ -119,15 +119,14 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {
|
|||||||
private _setLayoutMethod() {
|
private _setLayoutMethod() {
|
||||||
this.model.setLayoutMethod(function (
|
this.model.setLayoutMethod(function (
|
||||||
this: MindmapElementModel,
|
this: MindmapElementModel,
|
||||||
tree: MindmapNode | MindmapRoot = this.tree,
|
tree: MindmapNode | MindmapRoot | undefined,
|
||||||
options: {
|
options:
|
||||||
applyStyle?: boolean;
|
| {
|
||||||
layoutType?: LayoutType;
|
applyStyle?: boolean;
|
||||||
stashed?: boolean;
|
layoutType?: LayoutType;
|
||||||
} = {
|
stashed?: boolean;
|
||||||
applyStyle: true,
|
}
|
||||||
stashed: true,
|
| undefined
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
const { stashed, applyStyle, layoutType } = Object.assign(
|
const { stashed, applyStyle, layoutType } = Object.assign(
|
||||||
{
|
{
|
||||||
@@ -137,9 +136,10 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {
|
|||||||
},
|
},
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
const targetTree = tree ?? this.tree;
|
||||||
|
|
||||||
const pop = stashed ? this.stashTree(tree) : null;
|
const pop = stashed ? this.stashTree(targetTree) : null;
|
||||||
handleLayout(this, tree, applyStyle, layoutType);
|
handleLayout(this, targetTree, applyStyle, layoutType);
|
||||||
pop?.();
|
pop?.();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,7 @@ export const getSelectedModelsCommand: Command<
|
|||||||
])
|
])
|
||||||
.pipe(getSelectedBlocksCommand, { types, mode })
|
.pipe(getSelectedBlocksCommand, { types, mode })
|
||||||
.pipe(ctx => {
|
.pipe(ctx => {
|
||||||
const { selectedBlocks = [] } = ctx;
|
selectedModels.push(...ctx.selectedBlocks.map(el => el.model));
|
||||||
selectedModels.push(...selectedBlocks.map(el => el.model));
|
|
||||||
})
|
})
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
|||||||
@@ -374,10 +374,10 @@ export class CopilotEmbeddingJob {
|
|||||||
const docContent = await this.doc.getFullDocContent(workspaceId, docId);
|
const docContent = await this.doc.getFullDocContent(workspaceId, docId);
|
||||||
const authors = await this.models.doc.getAuthors(workspaceId, docId);
|
const authors = await this.models.doc.getAuthors(workspaceId, docId);
|
||||||
if (docContent && authors) {
|
if (docContent && authors) {
|
||||||
const { title = 'Untitled', summary } = docContent;
|
const { title, summary } = docContent;
|
||||||
const { createdAt, updatedAt, createdByUser, updatedByUser } = authors;
|
const { createdAt, updatedAt, createdByUser, updatedByUser } = authors;
|
||||||
return {
|
return {
|
||||||
title,
|
title: title || 'Untitled',
|
||||||
summary,
|
summary,
|
||||||
createdAt: createdAt.toDateString(),
|
createdAt: createdAt.toDateString(),
|
||||||
updatedAt: updatedAt.toDateString(),
|
updatedAt: updatedAt.toDateString(),
|
||||||
|
|||||||
@@ -255,9 +255,7 @@ export class LiveData<T = unknown>
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
initialValue: T,
|
initialValue: T,
|
||||||
upstream:
|
upstream?: (upstream: Observable<LiveDataOperation>) => Observable<T>
|
||||||
| ((upstream: Observable<LiveDataOperation>) => Observable<T>)
|
|
||||||
| undefined = undefined
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.raw$ = new BehaviorSubject(initialValue);
|
this.raw$ = new BehaviorSubject(initialValue);
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ impl PartialEq for Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Item {}
|
||||||
|
|
||||||
impl std::fmt::Debug for Item {
|
impl std::fmt::Debug for Item {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut dbg = f.debug_struct("Item");
|
let mut dbg = f.debug_struct("Item");
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ impl PartialEq for Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Node {
|
impl Eq for Node {}
|
||||||
fn assert_receiver_is_total_eq(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Item> for Node {
|
impl From<Item> for Node {
|
||||||
fn from(value: Item) -> Self {
|
fn from(value: Item) -> Self {
|
||||||
|
|||||||
@@ -299,9 +299,7 @@ impl<T: PartialEq> PartialEq for SomrInner<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PartialEq> Eq for Somr<T> {
|
impl<T: Eq> Eq for Somr<T> {}
|
||||||
fn assert_receiver_is_total_eq(&self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialOrd> PartialOrd for Somr<T> {
|
impl<T: PartialOrd> PartialOrd for Somr<T> {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ impl StoreHistory {
|
|||||||
|
|
||||||
// make items as reference
|
// make items as reference
|
||||||
let mut store_items = store_items.iter().collect::<Vec<_>>();
|
let mut store_items = store_items.iter().collect::<Vec<_>>();
|
||||||
store_items.sort_by(|a, b| a.id.clock.cmp(&b.id.clock));
|
store_items.sort_by_key(|item| item.id.clock);
|
||||||
|
|
||||||
self.parse_items(store_items)
|
self.parse_items(store_items)
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ impl StoreHistory {
|
|||||||
|
|
||||||
// make items as reference
|
// make items as reference
|
||||||
let mut store_items = store_items.iter().collect::<Vec<_>>();
|
let mut store_items = store_items.iter().collect::<Vec<_>>();
|
||||||
store_items.sort_by(|a, b| a.id.clock.cmp(&b.id.clock));
|
store_items.sort_by_key(|item| item.id.clock);
|
||||||
|
|
||||||
self.parse_items(store_items)
|
self.parse_items(store_items)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,11 +266,7 @@ fn advance_text_position(store: &mut DocStore, pos: &mut TextPosition, mut remai
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn minimize_attribute_changes(pos: &mut TextPosition, attrs: &TextAttributes) {
|
fn minimize_attribute_changes(pos: &mut TextPosition, attrs: &TextAttributes) {
|
||||||
loop {
|
while let Some(item) = pos.right.get() {
|
||||||
let Some(item) = pos.right.get() else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if item.deleted() {
|
if item.deleted() {
|
||||||
pos.forward();
|
pos.forward();
|
||||||
continue;
|
continue;
|
||||||
@@ -345,11 +341,7 @@ fn insert_negated_attributes(
|
|||||||
pos: &mut TextPosition,
|
pos: &mut TextPosition,
|
||||||
mut negated: TextAttributes,
|
mut negated: TextAttributes,
|
||||||
) -> JwstCodecResult {
|
) -> JwstCodecResult {
|
||||||
loop {
|
while let Some(item) = pos.right.get() {
|
||||||
let Some(item) = pos.right.get() else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if item.deleted() {
|
if item.deleted() {
|
||||||
pos.forward();
|
pos.forward();
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ export type AvatarProps = {
|
|||||||
removeButtonProps?: HTMLAttributes<HTMLButtonElement>;
|
removeButtonProps?: HTMLAttributes<HTMLButtonElement>;
|
||||||
} & HTMLAttributes<HTMLSpanElement>;
|
} & HTMLAttributes<HTMLSpanElement>;
|
||||||
|
|
||||||
|
const EMPTY_STYLE: CSSProperties = {};
|
||||||
|
const EMPTY_FALLBACK_PROPS: AvatarFallbackProps = {};
|
||||||
|
const EMPTY_HOVER_WRAPPER_PROPS: HTMLAttributes<HTMLDivElement> = {};
|
||||||
|
const EMPTY_REMOVE_BUTTON_PROPS: HTMLAttributes<HTMLButtonElement> = {};
|
||||||
|
|
||||||
function drawImageFit(
|
function drawImageFit(
|
||||||
img: ImageBitmap,
|
img: ImageBitmap,
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
@@ -88,32 +93,32 @@ export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
|||||||
(
|
(
|
||||||
{
|
{
|
||||||
size = 20,
|
size = 20,
|
||||||
style: propsStyles = {},
|
style: propsStyles = EMPTY_STYLE,
|
||||||
url,
|
url,
|
||||||
image,
|
image,
|
||||||
name,
|
name,
|
||||||
className,
|
className,
|
||||||
colorfulFallback = false,
|
colorfulFallback = false,
|
||||||
hoverIcon,
|
hoverIcon,
|
||||||
fallbackProps: { className: fallbackClassName, ...fallbackProps } = {},
|
fallbackProps = EMPTY_FALLBACK_PROPS,
|
||||||
imageProps,
|
imageProps,
|
||||||
avatarProps,
|
avatarProps,
|
||||||
rounded = '50%',
|
rounded = '50%',
|
||||||
onRemove,
|
onRemove,
|
||||||
hoverWrapperProps: {
|
hoverWrapperProps = EMPTY_HOVER_WRAPPER_PROPS,
|
||||||
className: hoverWrapperClassName,
|
|
||||||
...hoverWrapperProps
|
|
||||||
} = {},
|
|
||||||
avatarTooltipOptions,
|
avatarTooltipOptions,
|
||||||
removeTooltipOptions,
|
removeTooltipOptions,
|
||||||
removeButtonProps: {
|
removeButtonProps = EMPTY_REMOVE_BUTTON_PROPS,
|
||||||
className: removeButtonClassName,
|
|
||||||
...removeButtonProps
|
|
||||||
} = {},
|
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
|
const { className: fallbackClassName, ...otherFallbackProps } =
|
||||||
|
fallbackProps;
|
||||||
|
const { className: hoverWrapperClassName, ...otherHoverWrapperProps } =
|
||||||
|
hoverWrapperProps;
|
||||||
|
const { className: removeButtonClassName, ...otherRemoveButtonProps } =
|
||||||
|
removeButtonProps;
|
||||||
const firstCharOfName = useMemo(() => {
|
const firstCharOfName = useMemo(() => {
|
||||||
return name?.slice(0, 1);
|
return name?.slice(0, 1);
|
||||||
}, [name]);
|
}, [name]);
|
||||||
@@ -180,7 +185,7 @@ export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
|||||||
<AvatarFallback
|
<AvatarFallback
|
||||||
className={clsx(style.avatarFallback, fallbackClassName)}
|
className={clsx(style.avatarFallback, fallbackClassName)}
|
||||||
delayMs={url ? 600 : undefined}
|
delayMs={url ? 600 : undefined}
|
||||||
{...fallbackProps}
|
{...otherFallbackProps}
|
||||||
>
|
>
|
||||||
{colorfulFallback ? (
|
{colorfulFallback ? (
|
||||||
<ColorfulFallback char={firstCharOfName} />
|
<ColorfulFallback char={firstCharOfName} />
|
||||||
@@ -196,7 +201,7 @@ export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
|||||||
fallbackClassName
|
fallbackClassName
|
||||||
)}
|
)}
|
||||||
delayMs={url ? 600 : undefined}
|
delayMs={url ? 600 : undefined}
|
||||||
{...fallbackProps}
|
{...otherFallbackProps}
|
||||||
>
|
>
|
||||||
<DefaultFallbackSvg />
|
<DefaultFallbackSvg />
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
@@ -204,7 +209,7 @@ export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
|||||||
{hoverIcon ? (
|
{hoverIcon ? (
|
||||||
<div
|
<div
|
||||||
className={clsx(style.hoverWrapper, hoverWrapperClassName)}
|
className={clsx(style.hoverWrapper, hoverWrapperClassName)}
|
||||||
{...hoverWrapperProps}
|
{...otherHoverWrapperProps}
|
||||||
>
|
>
|
||||||
{hoverIcon}
|
{hoverIcon}
|
||||||
</div>
|
</div>
|
||||||
@@ -223,7 +228,7 @@ export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
|
|||||||
className={clsx(style.removeButton, removeButtonClassName)}
|
className={clsx(style.removeButton, removeButtonClassName)}
|
||||||
onClick={onRemove}
|
onClick={onRemove}
|
||||||
ref={setRemoveButtonDom}
|
ref={setRemoveButtonDom}
|
||||||
{...removeButtonProps}
|
{...otherRemoveButtonProps}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ export type InputProps = {
|
|||||||
onEnter?: (value: string) => void;
|
onEnter?: (value: string) => void;
|
||||||
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'onBlur'>;
|
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'onBlur'>;
|
||||||
|
|
||||||
|
const EMPTY_STYLE: CSSProperties = {};
|
||||||
|
|
||||||
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
||||||
{
|
{
|
||||||
disabled,
|
disabled,
|
||||||
@@ -34,8 +36,8 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|||||||
noBorder = false,
|
noBorder = false,
|
||||||
className,
|
className,
|
||||||
status = 'default',
|
status = 'default',
|
||||||
style = {},
|
style = EMPTY_STYLE,
|
||||||
inputStyle = {},
|
inputStyle = EMPTY_STYLE,
|
||||||
size = 'default',
|
size = 'default',
|
||||||
preFix,
|
preFix,
|
||||||
endFix,
|
endFix,
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ export type RowInputProps = {
|
|||||||
debounce?: number;
|
debounce?: number;
|
||||||
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'onBlur'>;
|
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size' | 'onBlur'>;
|
||||||
|
|
||||||
|
const EMPTY_STYLE: CSSProperties = {};
|
||||||
|
|
||||||
// RowInput component that is used in the selector layout for search input
|
// RowInput component that is used in the selector layout for search input
|
||||||
// handles composition events and enter key press
|
// handles composition events and enter key press
|
||||||
export const RowInput = forwardRef<HTMLInputElement, RowInputProps>(
|
export const RowInput = forwardRef<HTMLInputElement, RowInputProps>(
|
||||||
@@ -33,7 +35,7 @@ export const RowInput = forwardRef<HTMLInputElement, RowInputProps>(
|
|||||||
disabled,
|
disabled,
|
||||||
onChange: propsOnChange,
|
onChange: propsOnChange,
|
||||||
className,
|
className,
|
||||||
style = {},
|
style = EMPTY_STYLE,
|
||||||
onEnter,
|
onEnter,
|
||||||
onKeyDown,
|
onKeyDown,
|
||||||
onBlur,
|
onBlur,
|
||||||
|
|||||||
@@ -11,26 +11,26 @@ const MenuContextValue = {
|
|||||||
type: 'dropdown-menu',
|
type: 'dropdown-menu',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
const EMPTY_ROOT_OPTIONS: NonNullable<MenuProps['rootOptions']> = {};
|
||||||
|
const EMPTY_CONTENT_OPTIONS: NonNullable<MenuProps['contentOptions']> = {};
|
||||||
|
const EMPTY_CONTENT_STYLE: React.CSSProperties = {};
|
||||||
|
|
||||||
export const DesktopMenu = ({
|
export const DesktopMenu = ({
|
||||||
children,
|
children,
|
||||||
items,
|
items,
|
||||||
noPortal,
|
noPortal,
|
||||||
portalOptions,
|
portalOptions,
|
||||||
rootOptions: {
|
rootOptions: rawRootOptions,
|
||||||
defaultOpen,
|
contentOptions: rawContentOptions,
|
||||||
modal,
|
|
||||||
open,
|
|
||||||
onOpenChange,
|
|
||||||
onClose,
|
|
||||||
...rootOptions
|
|
||||||
} = {},
|
|
||||||
contentOptions: {
|
|
||||||
className = '',
|
|
||||||
style: contentStyle = {},
|
|
||||||
...otherContentOptions
|
|
||||||
} = {},
|
|
||||||
ref,
|
ref,
|
||||||
}: MenuProps) => {
|
}: MenuProps) => {
|
||||||
|
const { defaultOpen, modal, open, onOpenChange, onClose, ...rootOptions } =
|
||||||
|
rawRootOptions ?? EMPTY_ROOT_OPTIONS;
|
||||||
|
const {
|
||||||
|
className = '',
|
||||||
|
style: contentStyle = EMPTY_CONTENT_STYLE,
|
||||||
|
...otherContentOptions
|
||||||
|
} = rawContentOptions ?? EMPTY_CONTENT_OPTIONS;
|
||||||
const [innerOpen, setInnerOpen] = useState(defaultOpen);
|
const [innerOpen, setInnerOpen] = useState(defaultOpen);
|
||||||
const finalOpen = open ?? innerOpen;
|
const finalOpen = open ?? innerOpen;
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,25 @@ import * as styles from '../styles.css';
|
|||||||
import { useMenuItem } from '../use-menu-item';
|
import { useMenuItem } from '../use-menu-item';
|
||||||
import { DesktopMenuContext } from './context';
|
import { DesktopMenuContext } from './context';
|
||||||
|
|
||||||
|
const EMPTY_SUB_OPTIONS: NonNullable<MenuSubProps['subOptions']> = {};
|
||||||
|
const EMPTY_SUB_CONTENT_OPTIONS: NonNullable<
|
||||||
|
MenuSubProps['subContentOptions']
|
||||||
|
> = {};
|
||||||
|
|
||||||
export const DesktopMenuSub = ({
|
export const DesktopMenuSub = ({
|
||||||
children: propsChildren,
|
children: propsChildren,
|
||||||
items,
|
items,
|
||||||
portalOptions,
|
portalOptions,
|
||||||
subOptions: { defaultOpen, ...otherSubOptions } = {},
|
subOptions,
|
||||||
triggerOptions,
|
triggerOptions,
|
||||||
subContentOptions: {
|
subContentOptions,
|
||||||
|
}: MenuSubProps) => {
|
||||||
|
const { defaultOpen, ...otherSubOptions } = subOptions ?? EMPTY_SUB_OPTIONS;
|
||||||
|
const {
|
||||||
className: subContentClassName = '',
|
className: subContentClassName = '',
|
||||||
style: contentStyle,
|
style: contentStyle,
|
||||||
...otherSubContentOptions
|
...otherSubContentOptions
|
||||||
} = {},
|
} = subContentOptions ?? EMPTY_SUB_CONTENT_OPTIONS;
|
||||||
}: MenuSubProps) => {
|
|
||||||
const { type } = useContext(DesktopMenuContext);
|
const { type } = useContext(DesktopMenuContext);
|
||||||
const { className, children, otherProps } = useMenuItem({
|
const { className, children, otherProps } = useMenuItem({
|
||||||
children: propsChildren,
|
children: propsChildren,
|
||||||
|
|||||||
@@ -24,11 +24,18 @@ import {
|
|||||||
import * as styles from './styles.css';
|
import * as styles from './styles.css';
|
||||||
import { MobileMenuSubRaw } from './sub';
|
import { MobileMenuSubRaw } from './sub';
|
||||||
|
|
||||||
|
const EMPTY_CONTENT_OPTIONS: NonNullable<MenuProps['contentOptions']> = {};
|
||||||
|
|
||||||
export const MobileMenu = ({
|
export const MobileMenu = ({
|
||||||
children,
|
children,
|
||||||
items,
|
items,
|
||||||
title,
|
title,
|
||||||
contentOptions: {
|
contentOptions,
|
||||||
|
contentWrapperStyle,
|
||||||
|
rootOptions,
|
||||||
|
ref,
|
||||||
|
}: MenuProps) => {
|
||||||
|
const {
|
||||||
className,
|
className,
|
||||||
onPointerDownOutside,
|
onPointerDownOutside,
|
||||||
onInteractOutside,
|
onInteractOutside,
|
||||||
@@ -38,11 +45,7 @@ export const MobileMenu = ({
|
|||||||
align: _align,
|
align: _align,
|
||||||
|
|
||||||
...otherContentOptions
|
...otherContentOptions
|
||||||
} = {},
|
} = contentOptions ?? EMPTY_CONTENT_OPTIONS;
|
||||||
contentWrapperStyle,
|
|
||||||
rootOptions,
|
|
||||||
ref,
|
|
||||||
}: MenuProps) => {
|
|
||||||
const [subMenus, setSubMenus] = useState<SubMenuContent[]>([]);
|
const [subMenus, setSubMenus] = useState<SubMenuContent[]>([]);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const mobileContextValue = useMemo(
|
const mobileContextValue = useMemo(
|
||||||
|
|||||||
@@ -6,13 +6,18 @@ import type { MenuSubProps } from '../menu.types';
|
|||||||
import { useMenuItem } from '../use-menu-item';
|
import { useMenuItem } from '../use-menu-item';
|
||||||
import { useMobileSubMenuHelper } from './context';
|
import { useMobileSubMenuHelper } from './context';
|
||||||
|
|
||||||
|
const EMPTY_SUB_CONTENT_OPTIONS: NonNullable<
|
||||||
|
MenuSubProps['subContentOptions']
|
||||||
|
> = {};
|
||||||
|
|
||||||
export const MobileMenuSub = ({
|
export const MobileMenuSub = ({
|
||||||
title,
|
title,
|
||||||
children: propsChildren,
|
children: propsChildren,
|
||||||
items,
|
items,
|
||||||
triggerOptions,
|
triggerOptions,
|
||||||
subContentOptions: contentOptions = {},
|
subContentOptions,
|
||||||
}: MenuSubProps & { title?: string }) => {
|
}: MenuSubProps & { title?: string }) => {
|
||||||
|
const contentOptions = subContentOptions ?? EMPTY_SUB_CONTENT_OPTIONS;
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
@@ -43,11 +48,12 @@ export const MobileMenuSubRaw = ({
|
|||||||
children,
|
children,
|
||||||
items,
|
items,
|
||||||
subOptions,
|
subOptions,
|
||||||
subContentOptions: contentOptions = {},
|
subContentOptions,
|
||||||
}: MenuSubProps & {
|
}: MenuSubProps & {
|
||||||
onClick?: (e: MouseEvent<HTMLDivElement>) => void;
|
onClick?: (e: MouseEvent<HTMLDivElement>) => void;
|
||||||
title?: string;
|
title?: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const contentOptions = subContentOptions ?? EMPTY_SUB_CONTENT_OPTIONS;
|
||||||
const id = useId();
|
const id = useId();
|
||||||
const { addSubMenu } = useMobileSubMenuHelper();
|
const { addSubMenu } = useMobileSubMenuHelper();
|
||||||
|
|
||||||
|
|||||||
@@ -15,17 +15,21 @@ export interface PopoverProps extends PopoverPrimitiveProps {
|
|||||||
portalOptions?: PopoverPortalProps;
|
portalOptions?: PopoverPortalProps;
|
||||||
contentOptions?: PopoverContentProps;
|
contentOptions?: PopoverContentProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EMPTY_CONTENT_OPTIONS: NonNullable<PopoverProps['contentOptions']> = {};
|
||||||
|
|
||||||
export const Popover = ({
|
export const Popover = ({
|
||||||
content,
|
content,
|
||||||
children,
|
children,
|
||||||
portalOptions,
|
portalOptions,
|
||||||
contentOptions: {
|
contentOptions,
|
||||||
|
...props
|
||||||
|
}: PopoverProps) => {
|
||||||
|
const {
|
||||||
className: contentClassName,
|
className: contentClassName,
|
||||||
style: contentStyle,
|
style: contentStyle,
|
||||||
...otherContentOptions
|
...otherContentOptions
|
||||||
} = {},
|
} = contentOptions ?? EMPTY_CONTENT_OPTIONS;
|
||||||
...props
|
|
||||||
}: PopoverProps) => {
|
|
||||||
return (
|
return (
|
||||||
<PopoverPrimitive.Root {...props}>
|
<PopoverPrimitive.Root {...props}>
|
||||||
<PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>
|
<PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>
|
||||||
|
|||||||
+2
-7
@@ -428,13 +428,8 @@ export class AIChatComposer extends SignalWatcher(
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly addSelectedContextChip = async () => {
|
private readonly addSelectedContextChip = async () => {
|
||||||
const {
|
const { attachments, snapshot, combinedElementsMarkdown, docs, html } =
|
||||||
attachments = [],
|
this.chatContextValue;
|
||||||
snapshot,
|
|
||||||
combinedElementsMarkdown,
|
|
||||||
docs = [],
|
|
||||||
html,
|
|
||||||
} = this.chatContextValue;
|
|
||||||
await this.removeSelectedContextChip();
|
await this.removeSelectedContextChip();
|
||||||
const chip: SelectedContextChip = {
|
const chip: SelectedContextChip = {
|
||||||
uuid: uuidv4(),
|
uuid: uuidv4(),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export interface AIPanelErrorConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AIPanelGeneratingConfig {
|
export interface AIPanelGeneratingConfig {
|
||||||
generatingIcon: TemplateResult<1>;
|
generatingIcon?: TemplateResult<1>;
|
||||||
height?: number;
|
height?: number;
|
||||||
stages?: string[];
|
stages?: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,11 +67,14 @@ interface ErrorBaseProps {
|
|||||||
buttons?: ReactElement[];
|
buttons?: ReactElement[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_ICON = <FileIcon />;
|
||||||
|
const EMPTY_BUTTONS: ReactElement[] = [];
|
||||||
|
|
||||||
const ErrorBase = ({
|
const ErrorBase = ({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
icon = <FileIcon />,
|
icon = DEFAULT_ICON,
|
||||||
buttons = [],
|
buttons = EMPTY_BUTTONS,
|
||||||
}: ErrorBaseProps) => {
|
}: ErrorBaseProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={clsx([styles.viewer, styles.error])}>
|
<div className={clsx([styles.viewer, styles.error])}>
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import { AffineShapeIcon } from '..';
|
|||||||
import { SelectorLayout } from '../selector/selector-layout';
|
import { SelectorLayout } from '../selector/selector-layout';
|
||||||
import * as styles from './select-page.css';
|
import * as styles from './select-page.css';
|
||||||
|
|
||||||
|
const EMPTY_INIT: string[] = [];
|
||||||
|
|
||||||
export const SelectPage = memo(function SelectPage({
|
export const SelectPage = memo(function SelectPage({
|
||||||
init = [],
|
init = EMPTY_INIT,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
onCancel,
|
onCancel,
|
||||||
onChange: propsOnChange,
|
onChange: propsOnChange,
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ import { DropEffect } from './drop-effect';
|
|||||||
import * as styles from './node.css';
|
import * as styles from './node.css';
|
||||||
import type { NodeOperation } from './types';
|
import type { NodeOperation } from './types';
|
||||||
|
|
||||||
|
const EMPTY_OPERATIONS: NodeOperation[] = [];
|
||||||
|
|
||||||
export type NavigationPanelTreeNodeDropEffectData = {
|
export type NavigationPanelTreeNodeDropEffectData = {
|
||||||
source: { data: AffineDNDData['draggable'] };
|
source: { data: AffineDNDData['draggable'] };
|
||||||
treeInstruction: DropTargetTreeInstruction | null;
|
treeInstruction: DropTargetTreeInstruction | null;
|
||||||
@@ -190,9 +192,9 @@ export const NavigationPanelTreeNode = ({
|
|||||||
collapsible = true,
|
collapsible = true,
|
||||||
canDrop,
|
canDrop,
|
||||||
reorderable = true,
|
reorderable = true,
|
||||||
operations = [],
|
operations = EMPTY_OPERATIONS,
|
||||||
postfix,
|
postfix,
|
||||||
childrenOperations = [],
|
childrenOperations = EMPTY_OPERATIONS,
|
||||||
childrenPlaceholder,
|
childrenPlaceholder,
|
||||||
linkComponent: LinkComponent = WorkbenchLink,
|
linkComponent: LinkComponent = WorkbenchLink,
|
||||||
dndData,
|
dndData,
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import { NavigationPanelTreeContext } from './context';
|
|||||||
import * as styles from './root.css';
|
import * as styles from './root.css';
|
||||||
import type { NodeOperation } from './types';
|
import type { NodeOperation } from './types';
|
||||||
|
|
||||||
|
const EMPTY_OPERATIONS: NodeOperation[] = [];
|
||||||
|
|
||||||
export const NavigationPanelTreeRoot = ({
|
export const NavigationPanelTreeRoot = ({
|
||||||
children,
|
children,
|
||||||
childrenOperations = [],
|
childrenOperations = EMPTY_OPERATIONS,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: {
|
}: {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
export function BulledListIcon({ color = 'currentColor' }: { color: string }) {
|
export function BulledListIcon({ color = 'currentColor' }: { color?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width="16"
|
width="16"
|
||||||
|
|||||||
+3
-1
@@ -13,10 +13,12 @@ export interface AddItemPlaceholderProps extends HTMLAttributes<HTMLDivElement>
|
|||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_ICON = <PlusIcon />;
|
||||||
|
|
||||||
export const AddItemPlaceholder = ({
|
export const AddItemPlaceholder = ({
|
||||||
onClick,
|
onClick,
|
||||||
label = 'Add Item',
|
label = 'Add Item',
|
||||||
icon = <PlusIcon />,
|
icon = DEFAULT_ICON,
|
||||||
className,
|
className,
|
||||||
...attrs
|
...attrs
|
||||||
}: AddItemPlaceholderProps) => {
|
}: AddItemPlaceholderProps) => {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import * as styles from './node.css';
|
|||||||
|
|
||||||
interface NavigationPanelTreeNodeProps extends BaseNavigationPanelTreeNodeProps {}
|
interface NavigationPanelTreeNodeProps extends BaseNavigationPanelTreeNodeProps {}
|
||||||
|
|
||||||
|
const EMPTY_OPERATIONS: BaseNavigationPanelTreeNodeProps['operations'] = [];
|
||||||
|
|
||||||
export const NavigationPanelTreeNode = ({
|
export const NavigationPanelTreeNode = ({
|
||||||
children,
|
children,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
@@ -33,9 +35,9 @@ export const NavigationPanelTreeNode = ({
|
|||||||
collapsed,
|
collapsed,
|
||||||
extractEmojiAsIcon,
|
extractEmojiAsIcon,
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
operations = [],
|
operations = EMPTY_OPERATIONS,
|
||||||
postfix,
|
postfix,
|
||||||
childrenOperations = [],
|
childrenOperations = EMPTY_OPERATIONS,
|
||||||
childrenPlaceholder,
|
childrenPlaceholder,
|
||||||
linkComponent: LinkComponent = WorkbenchLink,
|
linkComponent: LinkComponent = WorkbenchLink,
|
||||||
...otherProps
|
...otherProps
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import { useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import * as styles from './root.css';
|
import * as styles from './root.css';
|
||||||
|
|
||||||
|
const EMPTY_OPERATIONS: NodeOperation[] = [];
|
||||||
|
|
||||||
export const NavigationPanelTreeRoot = ({
|
export const NavigationPanelTreeRoot = ({
|
||||||
children,
|
children,
|
||||||
childrenOperations = [],
|
childrenOperations = EMPTY_OPERATIONS,
|
||||||
placeholder,
|
placeholder,
|
||||||
}: {
|
}: {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
|||||||
@@ -33,11 +33,13 @@ export interface SettingDropdownSelectProps<
|
|||||||
native?: boolean;
|
native?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EMPTY_OPTIONS: DropdownItem<string>[] = [];
|
||||||
|
|
||||||
export const SettingDropdownSelect = <
|
export const SettingDropdownSelect = <
|
||||||
V extends string = string,
|
V extends string = string,
|
||||||
E extends boolean | undefined = true,
|
E extends boolean | undefined = true,
|
||||||
>({
|
>({
|
||||||
options = [],
|
options = EMPTY_OPTIONS as DropdownItem<V>[],
|
||||||
value,
|
value,
|
||||||
emitValue = true,
|
emitValue = true,
|
||||||
onChange,
|
onChange,
|
||||||
@@ -98,7 +100,7 @@ export const NativeSettingDropdownSelect = <
|
|||||||
V extends string = string,
|
V extends string = string,
|
||||||
E extends boolean | undefined = true,
|
E extends boolean | undefined = true,
|
||||||
>({
|
>({
|
||||||
options = [],
|
options = EMPTY_OPTIONS as DropdownItem<V>[],
|
||||||
value,
|
value,
|
||||||
emitValue = true,
|
emitValue = true,
|
||||||
onChange,
|
onChange,
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ const DatabaseBacklinkRow = ({
|
|||||||
row$,
|
row$,
|
||||||
onChange,
|
onChange,
|
||||||
}: {
|
}: {
|
||||||
defaultOpen: boolean;
|
defaultOpen?: boolean;
|
||||||
row$: Observable<DatabaseRow | undefined>;
|
row$: Observable<DatabaseRow | undefined>;
|
||||||
onChange?: (
|
onChange?: (
|
||||||
row: DatabaseRow,
|
row: DatabaseRow,
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import { HighlightText } from './highlight-text';
|
|||||||
|
|
||||||
type Groups = { group?: QuickSearchGroup; items: QuickSearchItem[] }[];
|
type Groups = { group?: QuickSearchGroup; items: QuickSearchItem[] }[];
|
||||||
|
|
||||||
|
const EMPTY_GROUPS: Groups = [];
|
||||||
|
|
||||||
export const CMDK = ({
|
export const CMDK = ({
|
||||||
className,
|
className,
|
||||||
query,
|
query,
|
||||||
groups: newGroups = [],
|
groups: newGroups = EMPTY_GROUPS,
|
||||||
error,
|
error,
|
||||||
inputLabel,
|
inputLabel,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Fragment, useMemo } from 'react';
|
|||||||
import * as styles from './highlight-text.css';
|
import * as styles from './highlight-text.css';
|
||||||
|
|
||||||
type HighlightProps = {
|
type HighlightProps = {
|
||||||
text: string;
|
text?: string;
|
||||||
start: string;
|
start: string;
|
||||||
end: string;
|
end: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -192,5 +192,5 @@ export const SUPPORTED_LANGUAGES: Record<
|
|||||||
originalName: 'Türkçe',
|
originalName: 'Türkçe',
|
||||||
flagEmoji: '🇹🇷',
|
flagEmoji: '🇹🇷',
|
||||||
resource: () => import('./tr.json'),
|
resource: () => import('./tr.json'),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1584,7 +1584,7 @@
|
|||||||
"com.affine.settings.workspace.experimental-features.enable-mind-map-import.name": "Zihin Haritası İçe Aktarımı",
|
"com.affine.settings.workspace.experimental-features.enable-mind-map-import.name": "Zihin Haritası İçe Aktarımı",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-mind-map-import.description": "Zihin haritasının içe aktarılmasını etkinleştirir.",
|
"com.affine.settings.workspace.experimental-features.enable-mind-map-import.description": "Zihin haritasının içe aktarılmasını etkinleştirir.",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-block-meta.name": "Blok Metaverisi",
|
"com.affine.settings.workspace.experimental-features.enable-block-meta.name": "Blok Metaverisi",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-block-meta.description": "Etkinleştirildiğinde, tüm bloklar için oluşturulma zamanı, güncellenme zamanı ile oluşturan ve güncelleyen bilgileri gösterilir.",
|
"com.affine.settings.workspace.experimental-features.enable-block-meta.description": "Etkinleştirildiğinde, tüm bloklar için oluşturulma zamanı, güncellenme zamanı ile oluşturan ve güncelleyen bilgileri gösterilir.",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-callout.name": "Belirtme çizgisi",
|
"com.affine.settings.workspace.experimental-features.enable-callout.name": "Belirtme çizgisi",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-callout.description": "Sözleriniz öne çıksın. Bu aynı zamanda transkripsiyon bloğundaki belirtme çizgisini de içerir.",
|
"com.affine.settings.workspace.experimental-features.enable-callout.description": "Sözleriniz öne çıksın. Bu aynı zamanda transkripsiyon bloğundaki belirtme çizgisini de içerir.",
|
||||||
"com.affine.settings.workspace.experimental-features.enable-embed-iframe-block.name": "Iframe Bloğunu Göm",
|
"com.affine.settings.workspace.experimental-features.enable-embed-iframe-block.name": "Iframe Bloğunu Göm",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export function createWavBuffer(
|
export function createWavBuffer(
|
||||||
samples: Float32Array,
|
samples: Float32Array,
|
||||||
options: {
|
options: {
|
||||||
sampleRate: number;
|
sampleRate?: number;
|
||||||
numChannels: number;
|
numChannels?: number;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const { sampleRate = 44100, numChannels = 1 } = options;
|
const { sampleRate = 44100, numChannels = 1 } = options;
|
||||||
|
|||||||
@@ -273,9 +273,7 @@ export class ChatPanelUtils {
|
|||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
const states = await page
|
const states = await page
|
||||||
.getByTestId('chat-panel-chip')
|
.getByTestId('chat-panel-chip')
|
||||||
.evaluateAll(elements =>
|
.evaluateAll(elements => elements.map(el => el.dataset.state));
|
||||||
elements.map(el => el.getAttribute('data-state'))
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(states.every(state => state === 'finished')).toBe(true);
|
expect(states.every(state => state === 'finished')).toBe(true);
|
||||||
}).toPass({ timeout: 20000 });
|
}).toPass({ timeout: 20000 });
|
||||||
@@ -283,9 +281,7 @@ export class ChatPanelUtils {
|
|||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
const states = await page
|
const states = await page
|
||||||
.getByTestId('chat-panel-chip')
|
.getByTestId('chat-panel-chip')
|
||||||
.evaluateAll(elements =>
|
.evaluateAll(elements => elements.map(el => el.dataset.state));
|
||||||
elements.map(el => el.getAttribute('data-state'))
|
|
||||||
);
|
|
||||||
expect(states).toHaveLength(attachments.length);
|
expect(states).toHaveLength(attachments.length);
|
||||||
expect(states.every(state => state === 'finished')).toBe(true);
|
expect(states.every(state => state === 'finished')).toBe(true);
|
||||||
}).toPass({ timeout: 20000 });
|
}).toPass({ timeout: 20000 });
|
||||||
|
|||||||
Reference in New Issue
Block a user