about summary refs log tree commit diff
path: root/src/state/queries
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-04-19 03:42:26 +0100
committerGitHub <noreply@github.com>2024-04-19 03:42:26 +0100
commitba1c4834ab23726c065aff31ef09e3578210ff01 (patch)
tree7c3335e22daf3b21e2e315d170b0936e0e26b5e6 /src/state/queries
parent20907381858b61fec61249c6ef836b9696e1ab05 (diff)
downloadvoidsky-ba1c4834ab23726c065aff31ef09e3578210ff01.tar.zst
Add GIF select to composer (#3600)
* create dialog with flatlist in it

* use alf for composer photos/camera/gif buttons

* add gif icons

* focus textinput on gif dialog close

* add giphy API + gif grid

* web support

* add consent confirmation

* track gif select

* desktop web consent styles

* use InlineLinkText instead of Link

* add error/loading state

* hide sideborders on web

* disable composer buttons where necessary

* skip cardyb and set thumbnail directly

* switch legacy analytics to statsig

* remove autoplay prop

* disable photo/gif buttons if external media is present

* memoize listmaybeplaceholder

* fix pagination

* don't set `value` of TextInput, clear via ref

* remove console.log

* close modal if press escape

* pass alt text in the description

* Fix typo

* Rm dialog

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'src/state/queries')
-rw-r--r--src/state/queries/giphy.ts280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/state/queries/giphy.ts b/src/state/queries/giphy.ts
new file mode 100644
index 000000000..ca5ff65f5
--- /dev/null
+++ b/src/state/queries/giphy.ts
@@ -0,0 +1,280 @@
+import {keepPreviousData, useInfiniteQuery} from '@tanstack/react-query'
+
+import {GIPHY_API_KEY, GIPHY_API_URL} from '#/lib/constants'
+
+export const RQKEY_ROOT = 'giphy'
+export const RQKEY_TRENDING = [RQKEY_ROOT, 'trending']
+export const RQKEY_SEARCH = (query: string) => [RQKEY_ROOT, 'search', query]
+
+const getTrendingGifs = createGiphyApi<
+  {
+    limit?: number
+    offset?: number
+    rating?: string
+    random_id?: string
+    bundle?: string
+  },
+  {data: Gif[]; pagination: Pagination}
+>('/v1/gifs/trending')
+
+const searchGifs = createGiphyApi<
+  {
+    q: string
+    limit?: number
+    offset?: number
+    rating?: string
+    lang?: string
+    random_id?: string
+    bundle?: string
+  },
+  {data: Gif[]; pagination: Pagination}
+>('/v1/gifs/search')
+
+export function useGiphyTrending() {
+  return useInfiniteQuery({
+    queryKey: RQKEY_TRENDING,
+    queryFn: ({pageParam}) => getTrendingGifs({offset: pageParam}),
+    initialPageParam: 0,
+    getNextPageParam: lastPage =>
+      lastPage.pagination.offset + lastPage.pagination.count,
+  })
+}
+
+export function useGifphySearch(query: string) {
+  return useInfiniteQuery({
+    queryKey: RQKEY_SEARCH(query),
+    queryFn: ({pageParam}) => searchGifs({q: query, offset: pageParam}),
+    initialPageParam: 0,
+    getNextPageParam: lastPage =>
+      lastPage.pagination.offset + lastPage.pagination.count,
+    enabled: !!query,
+    placeholderData: keepPreviousData,
+  })
+}
+
+function createGiphyApi<Input extends object, Ouput>(
+  path: string,
+): (input: Input) => Promise<
+  Ouput & {
+    meta: Meta
+  }
+> {
+  return async input => {
+    const url = new URL(path, GIPHY_API_URL)
+    url.searchParams.set('api_key', GIPHY_API_KEY)
+
+    for (const [key, value] of Object.entries(input)) {
+      url.searchParams.set(key, String(value))
+    }
+
+    const res = await fetch(url.toString(), {
+      method: 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+    })
+    if (!res.ok) {
+      throw new Error('Failed to fetch Giphy API')
+    }
+    return res.json()
+  }
+}
+
+export type Gif = {
+  type: string
+  id: string
+  slug: string
+  url: string
+  bitly_url: string
+  embed_url: string
+  username: string
+  source: string
+  rating: string
+  content_url: string
+  user: User
+  source_tld: string
+  source_post_url: string
+  update_datetime: string
+  create_datetime: string
+  import_datetime: string
+  trending_datetime: string
+  images: Images
+  title: string
+  alt_text: string
+}
+
+type Images = {
+  fixed_height: {
+    url: string
+    width: string
+    height: string
+    size: string
+    mp4: string
+    mp4_size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_height_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  fixed_height_downsampled: {
+    url: string
+    width: string
+    height: string
+    size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_width: {
+    url: string
+    width: string
+    height: string
+    size: string
+    mp4: string
+    mp4_size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_width_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  fixed_width_downsampled: {
+    url: string
+    width: string
+    height: string
+    size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_height_small: {
+    url: string
+    width: string
+    height: string
+    size: string
+    mp4: string
+    mp4_size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_height_small_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  fixed_width_small: {
+    url: string
+    width: string
+    height: string
+    size: string
+    mp4: string
+    mp4_size: string
+    webp: string
+    webp_size: string
+  }
+
+  fixed_width_small_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  downsized: {
+    url: string
+    width: string
+    height: string
+    size: string
+  }
+
+  downsized_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  downsized_large: {
+    url: string
+    width: string
+    height: string
+    size: string
+  }
+
+  downsized_medium: {
+    url: string
+    width: string
+    height: string
+    size: string
+  }
+
+  downsized_small: {
+    mp4: string
+    width: string
+    height: string
+    mp4_size: string
+  }
+
+  original: {
+    width: string
+    height: string
+    size: string
+    frames: string
+    mp4: string
+    mp4_size: string
+    webp: string
+    webp_size: string
+  }
+
+  original_still: {
+    url: string
+    width: string
+    height: string
+  }
+
+  looping: {
+    mp4: string
+  }
+
+  preview: {
+    mp4: string
+    mp4_size: string
+    width: string
+    height: string
+  }
+
+  preview_gif: {
+    url: string
+    width: string
+    height: string
+  }
+}
+
+type User = {
+  avatar_url: string
+  banner_url: string
+  profile_url: string
+  username: string
+  display_name: string
+}
+
+type Meta = {
+  msg: string
+  status: number
+  response_id: string
+}
+
+type Pagination = {
+  offset: number
+  total_count: number
+  count: number
+}