mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
fix(*): fix null assertion issues (#6682)
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { hsvToRgb } from './color-conversion';
|
||||
|
||||
interface IAlphaSliderProps {
|
||||
@@ -29,16 +29,19 @@ export function AlphaSlider({ hsv, alpha, onChange, onChanged }: IAlphaSliderPro
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const thumbRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const thumbSize = useMemo(() => {
|
||||
return thumbRef.current?.clientWidth ?? 0;
|
||||
}, [thumbRef.current]);
|
||||
|
||||
const calculateAlpha = useCallback((clientX: number) => {
|
||||
const slider = sliderRef.current;
|
||||
if (!slider) return;
|
||||
|
||||
const thumbSize = thumbRef.current?.clientWidth ?? 0;
|
||||
|
||||
const rect = slider.getBoundingClientRect();
|
||||
const maxX = rect.width - thumbSize;
|
||||
if (maxX <= 0) {
|
||||
onChange(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const x = Math.max(0, Math.min(clientX - rect.left, maxX));
|
||||
onChange(Math.round(x / maxX * 100) / 100);
|
||||
}, [onChange]);
|
||||
@@ -69,7 +72,11 @@ export function AlphaSlider({ hsv, alpha, onChange, onChanged }: IAlphaSliderPro
|
||||
|
||||
const getThumbPosition = () => {
|
||||
const safeAlpha = Math.min(Math.max(alpha * 100, 0), 100);
|
||||
return `${(safeAlpha / 100) * (100 - (thumbSize / sliderRef.current?.clientWidth! * 100))}%`;
|
||||
const thumbSize = thumbRef.current?.clientWidth ?? 0;
|
||||
const sliderWidth = sliderRef.current?.clientWidth ?? 0;
|
||||
const thumbOffsetPercent = sliderWidth > 0 ? (thumbSize / sliderWidth) * 100 : 0;
|
||||
|
||||
return `${(safeAlpha / 100) * (100 - thumbOffsetPercent)}%`;
|
||||
};
|
||||
|
||||
const color = hsvToRgb(...hsv);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface IHueSliderProps {
|
||||
hsv: [number, number, number];
|
||||
@@ -27,22 +27,24 @@ export function HueSlider({ hsv, onChange, onChanged }: IHueSliderProps) {
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const thumbRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const thumbSize = useMemo(() => {
|
||||
return thumbRef.current?.clientWidth ?? 0;
|
||||
}, []);
|
||||
|
||||
const calculateHue = useCallback((clientX: number) => {
|
||||
const slider = sliderRef.current;
|
||||
if (!slider) return;
|
||||
|
||||
const thumbSize = thumbRef.current?.clientWidth ?? 0;
|
||||
|
||||
const rect = slider.getBoundingClientRect();
|
||||
const maxX = rect.width - thumbSize;
|
||||
if (maxX <= 0) {
|
||||
onChange(0, hsv[1], hsv[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
const x = Math.max(0, Math.min(clientX - rect.left, maxX));
|
||||
|
||||
const newHue = Math.round((x / maxX) * 360);
|
||||
onChange(newHue, hsv[1], hsv[2]);
|
||||
}, [hsv, thumbSize, onChange]);
|
||||
}, [hsv, onChange]);
|
||||
|
||||
const handlePointerMove = useCallback((e: PointerEvent) => {
|
||||
e.stopPropagation();
|
||||
@@ -71,7 +73,11 @@ export function HueSlider({ hsv, onChange, onChanged }: IHueSliderProps) {
|
||||
|
||||
const getThumbPosition = () => {
|
||||
const safeHue = Math.min(Math.max(hsv[0], 0), 360);
|
||||
return `${(safeHue / 360) * (100 - (thumbSize / sliderRef.current?.clientWidth! * 100))}%`;
|
||||
const thumbSize = thumbRef.current?.clientWidth ?? 0;
|
||||
const sliderWidth = sliderRef.current?.clientWidth ?? 0;
|
||||
const thumbOffsetPercent = sliderWidth > 0 ? (thumbSize / sliderWidth) * 100 : 0;
|
||||
|
||||
return `${(safeHue / 360) * (100 - thumbOffsetPercent)}%`;
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -50,7 +50,7 @@ export interface IRadioProps {
|
||||
export function Radio(props: IRadioProps) {
|
||||
const { children, checked, value, disabled = false, onChange } = props;
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const inputRef = useRef<HTMLInputElement>(null!);
|
||||
|
||||
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
e.stopPropagation();
|
||||
@@ -60,7 +60,7 @@ export function Radio(props: IRadioProps) {
|
||||
if (typeof value !== 'undefined') {
|
||||
onChange && onChange(value);
|
||||
} else {
|
||||
const checked = inputRef?.current?.checked!;
|
||||
const checked = inputRef.current.checked;
|
||||
onChange && onChange(checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,8 +297,11 @@ export const DocTableInsertColumnCommand: ICommand<IDocTableInsertColumnCommandP
|
||||
|
||||
const pageWidth = (documentStyle.pageSize?.width ?? 800) - marginLeft - marginRight;
|
||||
|
||||
// eslint-disable-next-line ts/no-non-null-asserted-optional-chain
|
||||
const tableColumns = snapshot?.tableSource?.[tableId].tableColumns!;
|
||||
const tableColumns = snapshot?.tableSource?.[tableId]?.tableColumns;
|
||||
|
||||
if (!tableColumns) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { newColWidth, widths } = getColumnWidths(pageWidth, tableColumns, columnIndex);
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ
|
||||
};
|
||||
// clipboardHooks 应该被重新设计,用来处理多个 hook 处理同一个节点的能力
|
||||
// 参考 interceptor
|
||||
const onBeforePasteImage = (this._clipboardHooks.find((e) => e.onBeforePasteImage)?.onBeforePasteImage!) ?? fileToBase64;
|
||||
const onBeforePasteImage = this._clipboardHooks.find((e) => e.onBeforePasteImage)?.onBeforePasteImage ?? fileToBase64;
|
||||
|
||||
await Promise.all(files.map(async (file, index) => {
|
||||
const image = await onBeforePasteImage(file);
|
||||
|
||||
@@ -254,7 +254,7 @@ function processNode(node: DataStreamTreeNode, doc: IDocumentData, result: IHtml
|
||||
|
||||
case DataStreamTreeNodeType.PARAGRAPH: {
|
||||
const { children, startIndex, endIndex } = node;
|
||||
const paragraph = doc.body?.paragraphs!.find((p) => p.startIndex === endIndex) ?? {} as IParagraph;
|
||||
const paragraph = doc.body?.paragraphs?.find((p) => p.startIndex === endIndex) ?? {} as IParagraph;
|
||||
const { paragraphStyle = {} } = paragraph;
|
||||
const { spaceAbove, spaceBelow, lineSpacing } = paragraphStyle;
|
||||
const style = [];
|
||||
|
||||
@@ -368,10 +368,9 @@ function _divideOperator(
|
||||
} else {
|
||||
newGlyphGroup = [spanGroupCached[0]];
|
||||
}
|
||||
const column = currentLine.parent;
|
||||
const column = currentLine.parent!;
|
||||
|
||||
// eslint-disable-next-line ts/no-non-null-asserted-optional-chain
|
||||
const { paragraphStart: lineIsStart } = column?.lines.pop()!; // Delete the previous line and recalculate according to the maximum content height
|
||||
const { paragraphStart: lineIsStart } = column.lines.pop()!; // Delete the previous line and recalculate according to the maximum content height
|
||||
|
||||
_lineOperator(
|
||||
ctx,
|
||||
|
||||
@@ -27,7 +27,7 @@ import { useDocHight } from '../../formula-editor/hooks/use-highlight';
|
||||
export function useRangesHighlight(editor: Nullable<Editor>, focusing: boolean, unitId: string, subUnitId: string) {
|
||||
const lexerTreeBuilder = useDependency(LexerTreeBuilder);
|
||||
const highlightDoc = useDocHight('');
|
||||
const change = useObservable(editor?.getDocumentDataModel()!.change$);
|
||||
const change = useObservable(editor?.getDocumentDataModel()?.change$);
|
||||
const [sequenceNodes, setSequenceNodes] = useState<(string | ISequenceNode)[]>([]);
|
||||
const markSelectionService = useDependency(IMarkSelectionService);
|
||||
const last = useRef('');
|
||||
|
||||
@@ -270,7 +270,7 @@ export function RangeSelector(props: IRangeSelectorProps) {
|
||||
|
||||
const handleOpenModal = useEvent(() => {
|
||||
blurEditor();
|
||||
setRangeSelectorRanges(parseRanges(editor?.getDocumentDataModel()!.getPlainText() ?? ''));
|
||||
setRangeSelectorRanges(parseRanges(editor?.getDocumentDataModel()?.getPlainText() ?? ''));
|
||||
setPopupVisible(true);
|
||||
});
|
||||
|
||||
@@ -294,12 +294,12 @@ export function RangeSelector(props: IRangeSelectorProps) {
|
||||
setRangeSelectorRanges([]);
|
||||
setPopupVisible(false);
|
||||
},
|
||||
getValue: () => editor?.getDocumentDataModel()!.getPlainText() ?? '',
|
||||
getValue: () => editor?.getDocumentDataModel()?.getPlainText() ?? '',
|
||||
};
|
||||
}, [blurEditor, editor, editorService, selectorRef, sequenceNodesRef]);
|
||||
|
||||
useEffect(() => {
|
||||
onVerify?.(verifyRange(sequenceNodes), editor?.getDocumentDataModel()!.getPlainText() ?? '');
|
||||
onVerify?.(verifyRange(sequenceNodes), editor?.getDocumentDataModel()?.getPlainText() ?? '');
|
||||
}, [sequenceNodes]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -21,7 +21,6 @@ import { DeviceInputEventType } from '@univerjs/engine-render';
|
||||
import { ComponentManager, DISABLE_AUTO_FOCUS_KEY, MetaKeys, useDependency, useEvent, useObservable, useSidebarClick } from '@univerjs/ui';
|
||||
import * as React from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { SetCellEditVisibleArrowOperation, SetCellEditVisibleOperation } from '../../commands/operations/cell-edit.operation';
|
||||
import { EMBEDDING_FORMULA_EDITOR_COMPONENT_KEY } from '../../common/keys';
|
||||
import { IEditorBridgeService } from '../../services/editor-bridge.service';
|
||||
@@ -124,7 +123,7 @@ export const EditorContainer: React.FC<ICellIEditorProps> = () => {
|
||||
|
||||
useSidebarClick(handleClickSideBar);
|
||||
|
||||
const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId!);
|
||||
const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId);
|
||||
|
||||
const onMoveInEditor = useEvent((keycode: KeyCode, metaKey: MetaKeys) => {
|
||||
commandService.executeCommand(SetCellEditVisibleArrowOperation.id, {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useMemo } from 'react';
|
||||
import { SetCellEditVisibleOperation } from '../../commands/operations/cell-edit.operation';
|
||||
import { IEditorBridgeService } from '../../services/editor-bridge.service';
|
||||
|
||||
export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 | 2>, unitId: string) {
|
||||
export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 | 2>, unitId?: string) {
|
||||
const editorBridgeService = useDependency(IEditorBridgeService);
|
||||
const commandService = useDependency(ICommandService);
|
||||
|
||||
@@ -34,12 +34,16 @@ export function useKeyEventConfig(isRefSelecting: React.MutableRefObject<0 | 1 |
|
||||
],
|
||||
handler: (keycode: KeyCode) => {
|
||||
if (keycode === KeyCode.ENTER || keycode === KeyCode.ESC || keycode === KeyCode.TAB) {
|
||||
if (unitId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
editorBridgeService.disableForceKeepVisible();
|
||||
commandService.syncExecuteCommand(SetCellEditVisibleOperation.id, {
|
||||
visible: false,
|
||||
eventType: DeviceInputEventType.Keyboard,
|
||||
keycode,
|
||||
unitId: unitId!,
|
||||
unitId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -83,7 +83,7 @@ export function FormulaBar(props: IProps) {
|
||||
const workbook = useObservable(() => univerInstanceService.getCurrentTypeOfUnit$<Workbook>(UniverInstanceType.UNIVER_SHEET), undefined, undefined, [])!;
|
||||
const isRefSelecting = useRef<0 | 1 | 2>(0);
|
||||
const editState = useObservable(editorBridgeService.currentEditCellState$);
|
||||
const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId ?? '');
|
||||
const keyCodeConfig = useKeyEventConfig(isRefSelecting, editState?.unitId);
|
||||
const FormulaEditor = componentManager.get(EMBEDDING_FORMULA_EDITOR_COMPONENT_KEY);
|
||||
const formulaAuxUIParts = useComponentsOfPart(SheetsUIPart.FORMULA_AUX);
|
||||
const contextService = useDependency(IContextService);
|
||||
|
||||
@@ -54,9 +54,10 @@ export const DeleteRangeMoveUpCommand: ICommand = {
|
||||
if (!target) return false;
|
||||
|
||||
const { unitId, subUnitId, workbook, worksheet } = target;
|
||||
let range = params?.range;
|
||||
let range: IRange | undefined = params?.range;
|
||||
if (!range) {
|
||||
range = selectionManagerService.getCurrentLastSelection()?.range!;
|
||||
const currentSelection = selectionManagerService.getCurrentLastSelection();
|
||||
range = currentSelection?.range as IRange | undefined;
|
||||
}
|
||||
if (!range) return false;
|
||||
|
||||
|
||||
@@ -503,17 +503,21 @@ export const ThreadCommentTree = (props: IThreadCommentTreeProps) => {
|
||||
unitId={unitId}
|
||||
subUnitId={subUnitId}
|
||||
onSave={async ({ text, attachments }) => {
|
||||
if (!currentUser?.userID || !comments?.root) {
|
||||
throw new Error('[ThreadCommentTree] No current user or root comment found');
|
||||
}
|
||||
|
||||
const comment: IThreadComment = {
|
||||
text,
|
||||
attachments,
|
||||
dT: getDT(),
|
||||
id: generateRandomId(),
|
||||
ref: refStr!,
|
||||
personId: currentUser?.userID!,
|
||||
personId: currentUser?.userID,
|
||||
parentId: comments?.root.id,
|
||||
unitId,
|
||||
subUnitId,
|
||||
threadId: comments?.root.threadId!,
|
||||
threadId: comments?.root.threadId,
|
||||
};
|
||||
|
||||
if (onAddComment?.(comment) === false) {
|
||||
|
||||
Reference in New Issue
Block a user