このコミットが含まれているのは:
@@ -14,7 +14,8 @@ type Props = {
|
||||
type?: string
|
||||
placeholder?: string
|
||||
className?: string
|
||||
after?: ReactNode }
|
||||
after?: ReactNode
|
||||
onBlur?: () => void }
|
||||
|
||||
|
||||
const PostTextField: FC<Props> = (
|
||||
@@ -27,7 +28,8 @@ const PostTextField: FC<Props> = (
|
||||
type = 'text',
|
||||
placeholder,
|
||||
className,
|
||||
after },
|
||||
after,
|
||||
onBlur },
|
||||
) => (
|
||||
<FormField label={label} messages={errors}>
|
||||
{({ describedBy, invalid }) => (
|
||||
@@ -37,6 +39,7 @@ const PostTextField: FC<Props> = (
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
onBlur={onBlur}
|
||||
onChange={ev => onChange (ev.target.value)}
|
||||
aria-describedby={describedBy}
|
||||
aria-invalid={invalid}
|
||||
|
||||
@@ -74,12 +74,15 @@ const PostImportRowForm: FC<Props> = (
|
||||
const [messageRow, setMessageRow] = useState<PostImportRow | null> (null)
|
||||
const [saving, setSaving] = useState (false)
|
||||
const [resetRequested, setResetRequested] = useState (false)
|
||||
const [committedThumbnailBase, setCommittedThumbnailBase] = useState (
|
||||
() => String (row.attributes.thumbnailBase ?? ''))
|
||||
|
||||
useEffect (() => {
|
||||
const nextDraft = buildDraft (row)
|
||||
setDraft (nextDraft)
|
||||
setMessageRow (null)
|
||||
setResetRequested (false)
|
||||
setCommittedThumbnailBase (String (row.attributes.thumbnailBase ?? ''))
|
||||
}, [row])
|
||||
|
||||
const displayRow = messageRow ?? row
|
||||
@@ -118,6 +121,7 @@ const PostImportRowForm: FC<Props> = (
|
||||
setDraft (resetDraft)
|
||||
setResetRequested (true)
|
||||
setMessageRow (null)
|
||||
setCommittedThumbnailBase (resetDraft.thumbnailBase)
|
||||
return false
|
||||
}, [controls, resetDisabled, resetDraft])
|
||||
|
||||
@@ -159,7 +163,7 @@ const PostImportRowForm: FC<Props> = (
|
||||
<div className="grid gap-6 md:grid-cols-[7rem_minmax(0,1fr)]">
|
||||
<div className="space-y-3 md:sticky md:top-0 md:self-start">
|
||||
<PostImportThumbnailPreview
|
||||
url={draft.thumbnailBase}
|
||||
url={committedThumbnailBase}
|
||||
className="h-28 w-28"/>
|
||||
</div>
|
||||
|
||||
@@ -183,6 +187,10 @@ const PostImportRowForm: FC<Props> = (
|
||||
errors={groupedMessages (
|
||||
displayRow.validationErrors.thumbnailBase,
|
||||
displayRow.importErrors?.thumbnailBase)}
|
||||
onBlur={() => {
|
||||
if (draft.thumbnailBase !== committedThumbnailBase)
|
||||
setCommittedThumbnailBase (draft.thumbnailBase)
|
||||
}}
|
||||
onChange={value => update ('thumbnailBase', value)}/>
|
||||
</>}
|
||||
core={{
|
||||
|
||||
@@ -30,15 +30,16 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
if (!(url))
|
||||
return
|
||||
|
||||
let active = true
|
||||
const controller = new AbortController ()
|
||||
|
||||
const loadPreview = async () => {
|
||||
try
|
||||
{
|
||||
const blob = await apiGet<Blob> ('/preview/thumbnail', {
|
||||
const blob = await apiGet<Blob> ('/preview/image', {
|
||||
params: { url },
|
||||
signal: controller.signal,
|
||||
responseType: 'blob' })
|
||||
if (!(active))
|
||||
if (controller.signal.aborted)
|
||||
return
|
||||
|
||||
const nextPreviewUrl = URL.createObjectURL (blob)
|
||||
@@ -47,7 +48,7 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (active)
|
||||
if (!(controller.signal.aborted))
|
||||
setPreviewUrl ('')
|
||||
}
|
||||
}
|
||||
@@ -55,7 +56,7 @@ const PostImportThumbnailPreview: FC<Props> = (
|
||||
void loadPreview ()
|
||||
|
||||
return () => {
|
||||
active = false
|
||||
controller.abort ()
|
||||
if (previewUrlRef.current)
|
||||
{
|
||||
URL.revokeObjectURL (previewUrlRef.current)
|
||||
|
||||
新しい課題から参照
ユーザをブロックする