このコミットが含まれているのは:
@@ -49,6 +49,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
const [url, setURL] = useState ('')
|
||||
|
||||
const thumbnailPreviewRef = useRef ('')
|
||||
const urlRef = useRef ('')
|
||||
const videoFlg =
|
||||
useMemo (() => tags.split (/\s+/).some (tag => tag.replace (/\[.*\]$/, '') === '動画'),
|
||||
[tags])
|
||||
@@ -84,11 +85,13 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
}
|
||||
|
||||
const fetchTitle = useCallback (async () => {
|
||||
setTitleLoading (true)
|
||||
const requestedURL = url
|
||||
setTitleLoading (true)
|
||||
try
|
||||
{
|
||||
const data = await apiGet<{ title: string }> ('/preview/title', { params: { url } })
|
||||
setTitle (data.title || '')
|
||||
if (requestedURL === urlRef.current)
|
||||
setTitle (current => current || data.title || '')
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -97,6 +100,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
}, [url])
|
||||
|
||||
const fetchThumbnail = useCallback (async () => {
|
||||
const requestedURL = url
|
||||
setThumbnailPreview ('')
|
||||
setThumbnailFile (null)
|
||||
setThumbnailLoading (true)
|
||||
@@ -107,10 +111,13 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
const data = await apiGet<Blob> ('/preview/thumbnail',
|
||||
{ params: { url }, responseType: 'blob' })
|
||||
const imageURL = URL.createObjectURL (data)
|
||||
setThumbnailPreview (imageURL)
|
||||
setThumbnailFile (new File ([data],
|
||||
'thumbnail.png',
|
||||
{ type: data.type || 'image/png' }))
|
||||
if (requestedURL === urlRef.current)
|
||||
{
|
||||
setThumbnailPreview (current => current || imageURL)
|
||||
setThumbnailFile (current => current || new File ([data],
|
||||
'thumbnail.png',
|
||||
{ type: data.type || 'image/png' }))
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -122,6 +129,20 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
thumbnailPreviewRef.current = thumbnailPreview
|
||||
}, [thumbnailPreview])
|
||||
|
||||
useEffect (() => {
|
||||
urlRef.current = url
|
||||
}, [url])
|
||||
|
||||
useEffect (() => {
|
||||
if (!(url))
|
||||
return
|
||||
const timer = window.setTimeout (() => {
|
||||
fetchTitle ().catch (() => undefined)
|
||||
fetchThumbnail ().catch (() => undefined)
|
||||
}, 500)
|
||||
return () => window.clearTimeout (timer)
|
||||
}, [fetchThumbnail, fetchTitle, url])
|
||||
|
||||
if (!(editable))
|
||||
return <Forbidden/>
|
||||
|
||||
@@ -159,7 +180,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
onChange={ev => setTitle (ev.target.value)}
|
||||
disabled={titleLoading}/>
|
||||
<div className="flex flex-wrap items-center gap-2 text-sm">
|
||||
<span>必要なタイミングで URL から取得できます.</span>
|
||||
<span>URL 入力後に自動取得します.</span>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
@@ -176,7 +197,7 @@ const PostNewPage: FC<Props> = ({ user }) => {
|
||||
{({ describedBy, invalid }) => (
|
||||
<>
|
||||
<div className="mb-2 flex flex-wrap items-center gap-2 text-sm">
|
||||
<span>必要なタイミングで URL から取得できます.</span>
|
||||
<span>URL 入力後に自動取得します.</span>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
|
||||
新しい課題から参照
ユーザをブロックする