-
Notifications
You must be signed in to change notification settings - Fork 336
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: gifabol (tenor search) (#10735)
Signed-off-by: Matt Krick <[email protected]>
- Loading branch information
Showing
22 changed files
with
576 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
packages/client/tiptap/extensions/imageUpload/ImageSelectorSearchTab.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import type {Editor} from '@tiptap/core' | ||
import graphql from 'babel-plugin-relay/macro' | ||
import {useRef} from 'react' | ||
import {usePaginationFragment, usePreloadedQuery, type PreloadedQuery} from 'react-relay' | ||
import type {ImageSelectorSearchTabPaginationQuery} from '../../../__generated__/ImageSelectorSearchTabPaginationQuery.graphql' | ||
import type {ImageSelectorSearchTabQuery} from '../../../__generated__/ImageSelectorSearchTabQuery.graphql' | ||
import type {ImageSelectorSearchTabQuery_query$key} from '../../../__generated__/ImageSelectorSearchTabQuery_query.graphql' | ||
import useLoadNextOnScrollBottom from '../../../hooks/useLoadNextOnScrollBottom' | ||
import {cn} from '../../../ui/cn' | ||
|
||
interface Props { | ||
editor: Editor | ||
queryRef: PreloadedQuery<ImageSelectorSearchTabQuery> | ||
searchQuery: string | ||
setSearchQuery: (query: string) => void | ||
setImageURL: (url: string) => void | ||
} | ||
|
||
export const ImageSelectorSearchTab = (props: Props) => { | ||
const {queryRef, setImageURL, searchQuery, setSearchQuery} = props | ||
const ref = useRef<HTMLInputElement>(null) | ||
|
||
const query = usePreloadedQuery<ImageSelectorSearchTabQuery>( | ||
graphql` | ||
query ImageSelectorSearchTabQuery($query: String!, $fetchOriginal: Boolean!) { | ||
...ImageSelectorSearchTabQuery_query | ||
} | ||
`, | ||
queryRef | ||
) | ||
|
||
const paginationRes = usePaginationFragment< | ||
ImageSelectorSearchTabPaginationQuery, | ||
ImageSelectorSearchTabQuery_query$key | ||
>( | ||
graphql` | ||
fragment ImageSelectorSearchTabQuery_query on Query | ||
@argumentDefinitions(after: {type: "String"}, first: {type: "Int", defaultValue: 20}) | ||
@refetchable(queryName: "ImageSelectorSearchTabPaginationQuery") { | ||
searchGifs(query: $query, first: $first, after: $after) | ||
@connection(key: "ImageSelectorSearchTabQuery_searchGifs") { | ||
edges { | ||
node { | ||
previewUrl: url(size: tiny) | ||
originalUrl: url(size: original) @include(if: $fetchOriginal) | ||
} | ||
} | ||
} | ||
} | ||
`, | ||
query | ||
) | ||
const {data} = paginationRes | ||
const {searchGifs} = data | ||
const {edges} = searchGifs! | ||
const service = window.__ACTION__.GIF_PROVIDER | ||
// Per attribution spec, the exact wording is required | ||
// https://developers.google.com/tenor/guides/attribution | ||
const placeholder = service === 'tenor' ? 'Search Tenor' : 'Search Gifs' | ||
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const nextValue = e.target.value | ||
setSearchQuery(nextValue) | ||
} | ||
const lastItem = useLoadNextOnScrollBottom(paginationRes, {}, 20) | ||
return ( | ||
<div className='flex flex-col overflow-hidden'> | ||
<form className='flex w-full min-w-44 flex-col items-center justify-center space-y-3 rounded-md bg-slate-100 p-2'> | ||
<input | ||
autoFocus | ||
placeholder={placeholder} | ||
value={searchQuery} | ||
className='w-full outline-none focus:ring-2' | ||
ref={ref} | ||
onChange={onChange} | ||
/> | ||
</form> | ||
<div className='grid w-96 auto-rows-[1px] grid-cols-[repeat(auto-fit,_minmax(112px,_1fr))] gap-x-1 overflow-auto'> | ||
{edges.map((edge) => { | ||
const {node} = edge | ||
const {previewUrl, originalUrl} = node | ||
return ( | ||
<button | ||
key={previewUrl} | ||
style={{gridRow: 'span 200'}} // initially too tall to prevent the lastItem from intersecting viewport | ||
className={cn('row-span w-full cursor-pointer rounded')} | ||
onClick={() => { | ||
setImageURL(originalUrl || previewUrl) | ||
}} | ||
> | ||
<img | ||
src={previewUrl} | ||
className='rounded' | ||
onLoad={(e) => { | ||
const img = e.target as HTMLImageElement | ||
const button = img.parentElement! | ||
button.style.setProperty('grid-row', `span ${img.height + 2}`) | ||
}} | ||
/> | ||
</button> | ||
) | ||
})} | ||
{lastItem} | ||
</div> | ||
</div> | ||
) | ||
} |
39 changes: 39 additions & 0 deletions
39
packages/client/tiptap/extensions/imageUpload/ImageSelectorSearchTabRoot.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import type {Editor} from '@tiptap/core' | ||
import {Suspense, useState} from 'react' | ||
import useQueryLoaderNow from '~/hooks/useQueryLoaderNow' | ||
import type {ImageSelectorSearchTabQuery} from '../../../__generated__/ImageSelectorSearchTabQuery.graphql' | ||
import imageSelectorSearchTabQuery from '../../../__generated__/ImageSelectorSearchTabQuery.graphql' | ||
import {ImageSelectorSearchTab} from './ImageSelectorSearchTab' | ||
interface Props { | ||
editor: Editor | ||
setImageURL: (url: string) => void | ||
} | ||
|
||
export const ImageSelectorSearchTabRoot = (props: Props) => { | ||
const {editor} = props | ||
const [searchQuery, setSearchQuery] = useState('') | ||
const queryToSendToServer = searchQuery.length > 2 ? searchQuery : '' | ||
const queryRef = useQueryLoaderNow<ImageSelectorSearchTabQuery>( | ||
imageSelectorSearchTabQuery, | ||
{ | ||
fetchOriginal: editor.storage.imageUpload.editorWidth > 500, | ||
query: queryToSendToServer | ||
}, | ||
undefined, | ||
true | ||
) | ||
|
||
return ( | ||
<Suspense fallback={''}> | ||
{queryRef && ( | ||
<ImageSelectorSearchTab | ||
{...props} | ||
searchQuery={searchQuery} | ||
setSearchQuery={setSearchQuery} | ||
queryRef={queryRef} | ||
/> | ||
)} | ||
</Suspense> | ||
) | ||
} | ||
export default ImageSelectorSearchTabRoot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.