From fccd6b4ca8ed7420f25f0c4298fde311bc1e09d0 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 4 Jun 2020 00:18:50 +0800 Subject: refactor(front): Make codes lint-clean! --- Timeline/ClientApp/src/common/AppBar.tsx | 2 +- Timeline/ClientApp/src/common/ImageCropper.tsx | 40 +++++++++++++++-------- Timeline/ClientApp/src/common/OperationDialog.tsx | 35 ++++++++++---------- 3 files changed, 45 insertions(+), 32 deletions(-) (limited to 'Timeline/ClientApp/src/common') diff --git a/Timeline/ClientApp/src/common/AppBar.tsx b/Timeline/ClientApp/src/common/AppBar.tsx index 39794b0f..4f61798c 100644 --- a/Timeline/ClientApp/src/common/AppBar.tsx +++ b/Timeline/ClientApp/src/common/AppBar.tsx @@ -10,7 +10,7 @@ import { useOptionalVersionedAvatarUrl } from '../user/api'; import TimelineLogo from './TimelineLogo'; -const AppBar: React.FC<{}> = (_) => { +const AppBar: React.FC = (_) => { const history = useHistory(); const user = useUser(); const avatarUrl = useOptionalVersionedAvatarUrl(user?._links?.avatar); diff --git a/Timeline/ClientApp/src/common/ImageCropper.tsx b/Timeline/ClientApp/src/common/ImageCropper.tsx index 3ef35b44..fb9bb4f9 100644 --- a/Timeline/ClientApp/src/common/ImageCropper.tsx +++ b/Timeline/ClientApp/src/common/ImageCropper.tsx @@ -1,6 +1,8 @@ import * as React from 'react'; import clsx from 'clsx'; +import { UiLogicError } from '../common'; + export interface Clip { left: number; top: number; @@ -58,11 +60,11 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { const c = normalizeClip(clip); - const imgElement = React.useRef(null); + const imgElementRef = React.useRef(null); const onImageRef = React.useCallback( (e: HTMLImageElement | null) => { - imgElement.current = e; + imgElementRef.current = e; if (imageElementCallback != null && e == null) { imageElementCallback(null); } @@ -123,9 +125,13 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { const movement = { x: e.clientX - oldState.x, y: e.clientY - oldState.y }; + const { current: imgElement } = imgElementRef; + + if (imgElement == null) throw new UiLogicError('Image element is null.'); + const moveRatio = { - x: movement.x / imgElement.current!.width, - y: movement.y / imgElement.current!.height, + x: movement.x / imgElement.width, + y: movement.y / imgElement.height, }; const newRatio = { @@ -158,9 +164,13 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { const ratio = imageInfo == null ? 1 : imageInfo.ratio; + const { current: imgElement } = imgElementRef; + + if (imgElement == null) throw new UiLogicError('Image element is null.'); + const moveRatio = { - x: movement.x / imgElement.current!.width, - y: movement.x / imgElement.current!.width / ratio, + x: movement.x / imgElement.width, + y: movement.x / imgElement.width / ratio, }; const newRatio = { @@ -189,6 +199,8 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { [imageInfo, oldState, onChange] ); + const toPercentage = (n: number): string => `${n}%`; + // fuck!!! I just can't find a better way to implement this in pure css const containerStyle: React.CSSProperties = (() => { if (imageInfo == null) { @@ -196,14 +208,14 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { } else { if (imageInfo.ratio > 1) { return { - width: 100 / imageInfo.ratio + '%', + width: toPercentage(100 / imageInfo.ratio), paddingTop: '100%', height: 0, }; } else { return { width: '100%', - paddingTop: 100 * imageInfo.ratio + '%', + paddingTop: toPercentage(100 * imageInfo.ratio), height: 0, }; } @@ -221,10 +233,10 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { className="image-cropper-mask" touch-action="none" style={{ - left: c.left * 100 + '%', - top: c.top * 100 + '%', - width: c.width * 100 + '%', - height: c.height * 100 + '%', + left: toPercentage(c.left * 100), + top: toPercentage(c.top * 100), + width: toPercentage(c.width * 100), + height: toPercentage(c.height * 100), }} onPointerMove={onPointerMove} onPointerDown={onPointerDown} @@ -235,8 +247,8 @@ const ImageCropper = (props: ImageCropperProps): React.ReactElement => { className="image-cropper-handler" touch-action="none" style={{ - left: 'calc(' + (c.left + c.width) * 100 + '% - 15px)', - top: 'calc(' + (c.top + c.height) * 100 + '% - 15px)', + left: `calc(${(c.left + c.width) * 100}% - 15px)`, + top: `calc(${(c.top + c.height) * 100}% - 15px)`, }} onPointerMove={onHandlerPointerMove} onPointerDown={onPointerDown} diff --git a/Timeline/ClientApp/src/common/OperationDialog.tsx b/Timeline/ClientApp/src/common/OperationDialog.tsx index e7b6612c..501a353e 100644 --- a/Timeline/ClientApp/src/common/OperationDialog.tsx +++ b/Timeline/ClientApp/src/common/OperationDialog.tsx @@ -1,4 +1,4 @@ -import React, { useState, InputHTMLAttributes } from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Spinner, @@ -12,10 +12,12 @@ import { Button, Modal, ModalHeader, - FormText + FormText, } from 'reactstrap'; -const DefaultProcessPrompt: React.FC = _ => { +import { UiLogicError } from '../common'; + +const DefaultProcessPrompt: React.FC = (_) => { return ( @@ -27,7 +29,7 @@ interface DefaultErrorPromptProps { error?: string; } -const DefaultErrorPrompt: React.FC = props => { +const DefaultErrorPrompt: React.FC = (props) => { const { t } = useTranslation(); let result =

{t('operationDialog.error')}

; @@ -111,7 +113,7 @@ interface OperationDialogProps { onSuccessAndClose?: () => void; } -const OperationDialog: React.FC = props => { +const OperationDialog: React.FC = (props) => { const inputScheme = props.inputScheme ?? []; const { t } = useTranslation(); @@ -119,13 +121,13 @@ const OperationDialog: React.FC = props => { type Step = 'input' | 'process' | OperationResult; const [step, setStep] = useState('input'); const [values, setValues] = useState<(boolean | string)[]>( - inputScheme.map(i => { + inputScheme.map((i) => { if (i.type === 'bool') { return i.initValue ?? false; } else if (i.type === 'text' || i.type === 'select') { return i.initValue ?? ''; } else { - throw new Error('Unknown input scheme.'); + throw new UiLogicError('Unknown input scheme.'); } }) ); @@ -149,16 +151,16 @@ const OperationDialog: React.FC = props => { const onConfirm = (): void => { setStep('process'); props.onProcess(values).then( - d => { + (d: unknown) => { setStep({ type: 'success', - data: d + data: d, }); }, - e => { + (e: unknown) => { setStep({ type: 'failure', - data: e + data: e, }); } ); @@ -205,8 +207,7 @@ const OperationDialog: React.FC = props => { const newInputError: OperationInputErrorInfo = { ...oldError }; for (const [index, error] of Object.entries(newError)) { if (error !== undefined) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (newInputError as any)[index] = error; + newInputError[+index] = error as OperationInputOptionalError; } } return newInputError; @@ -236,7 +237,7 @@ const OperationDialog: React.FC = props => { {inputPrompt} {inputScheme.map((item, index) => { const value = values[index]; - const error: string | undefined = (e => + const error: string | undefined = ((e) => typeof e === 'string' ? t(e) : undefined)(inputError?.[index]); if (item.type === 'text') { @@ -246,7 +247,7 @@ const OperationDialog: React.FC = props => { { + onChange={(e) => { const v = e.target.value; const newValues = updateValue(index, v); setInputError( @@ -270,7 +271,7 @@ const OperationDialog: React.FC = props => { { + onChange={(e) => { updateValue( index, (e.target as HTMLInputElement).checked @@ -287,7 +288,7 @@ const OperationDialog: React.FC = props => { { + onChange={(event) => { updateValue(index, event.target.value); }} > -- cgit v1.2.3