hooks.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import {
  2. useCallback,
  3. useEffect,
  4. useState,
  5. } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import { useDebounceFn } from 'ahooks'
  8. import type {
  9. Plugin,
  10. } from '../types'
  11. import type {
  12. CollectionsAndPluginsSearchParams,
  13. MarketplaceCollection,
  14. PluginsSearchParams,
  15. } from './types'
  16. import {
  17. getFormattedPlugin,
  18. getMarketplaceCollectionsAndPlugins,
  19. } from './utils'
  20. import i18n from '@/i18n/i18next-config'
  21. import {
  22. useMutationPluginsFromMarketplace,
  23. } from '@/service/use-plugins'
  24. export const useMarketplaceCollectionsAndPlugins = () => {
  25. const [isLoading, setIsLoading] = useState(false)
  26. const [isSuccess, setIsSuccess] = useState(false)
  27. const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>()
  28. const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>()
  29. const queryMarketplaceCollectionsAndPlugins = useCallback(async (query?: CollectionsAndPluginsSearchParams) => {
  30. try {
  31. setIsLoading(true)
  32. setIsSuccess(false)
  33. const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins(query)
  34. setIsLoading(false)
  35. setIsSuccess(true)
  36. setMarketplaceCollections(marketplaceCollections)
  37. setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap)
  38. }
  39. // eslint-disable-next-line unused-imports/no-unused-vars
  40. catch (e) {
  41. setIsLoading(false)
  42. setIsSuccess(false)
  43. }
  44. }, [])
  45. return {
  46. marketplaceCollections,
  47. setMarketplaceCollections,
  48. marketplaceCollectionPluginsMap,
  49. setMarketplaceCollectionPluginsMap,
  50. queryMarketplaceCollectionsAndPlugins,
  51. isLoading,
  52. isSuccess,
  53. }
  54. }
  55. export const useMarketplacePlugins = () => {
  56. const {
  57. data,
  58. mutateAsync,
  59. reset,
  60. isPending,
  61. } = useMutationPluginsFromMarketplace()
  62. const [prevPlugins, setPrevPlugins] = useState<Plugin[] | undefined>()
  63. const resetPlugins = useCallback(() => {
  64. reset()
  65. setPrevPlugins(undefined)
  66. }, [reset])
  67. const handleUpdatePlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => {
  68. mutateAsync(pluginsSearchParams).then((res) => {
  69. const currentPage = pluginsSearchParams.page || 1
  70. const resPlugins = res.data.bundles || res.data.plugins
  71. if (currentPage > 1) {
  72. setPrevPlugins(prevPlugins => [...(prevPlugins || []), ...resPlugins.map((plugin) => {
  73. return getFormattedPlugin(plugin)
  74. })])
  75. }
  76. else {
  77. setPrevPlugins(resPlugins.map((plugin) => {
  78. return getFormattedPlugin(plugin)
  79. }))
  80. }
  81. })
  82. }, [mutateAsync])
  83. const queryPlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => {
  84. handleUpdatePlugins(pluginsSearchParams)
  85. }, [handleUpdatePlugins])
  86. const { run: queryPluginsWithDebounced, cancel: cancelQueryPluginsWithDebounced } = useDebounceFn((pluginsSearchParams: PluginsSearchParams) => {
  87. handleUpdatePlugins(pluginsSearchParams)
  88. }, {
  89. wait: 500,
  90. })
  91. return {
  92. plugins: prevPlugins,
  93. total: data?.data?.total,
  94. resetPlugins,
  95. queryPlugins,
  96. queryPluginsWithDebounced,
  97. cancelQueryPluginsWithDebounced,
  98. isLoading: isPending,
  99. }
  100. }
  101. export const useMixedTranslation = (localeFromOuter?: string) => {
  102. let t = useTranslation().t
  103. if (localeFromOuter)
  104. t = i18n.getFixedT(localeFromOuter)
  105. return {
  106. t,
  107. }
  108. }
  109. export const useMarketplaceContainerScroll = (
  110. callback: () => void,
  111. scrollContainerId = 'marketplace-container',
  112. ) => {
  113. const container = document.getElementById(scrollContainerId)
  114. const handleScroll = useCallback((e: Event) => {
  115. const target = e.target as HTMLDivElement
  116. const {
  117. scrollTop,
  118. scrollHeight,
  119. clientHeight,
  120. } = target
  121. if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0)
  122. callback()
  123. }, [callback])
  124. useEffect(() => {
  125. if (container)
  126. container.addEventListener('scroll', handleScroll)
  127. return () => {
  128. if (container)
  129. container.removeEventListener('scroll', handleScroll)
  130. }
  131. }, [container, handleScroll])
  132. }
  133. export const useSearchBoxAutoAnimate = (searchBoxAutoAnimate?: boolean) => {
  134. const [searchBoxCanAnimate, setSearchBoxCanAnimate] = useState(true)
  135. const handleSearchBoxCanAnimateChange = useCallback(() => {
  136. if (!searchBoxAutoAnimate) {
  137. const clientWidth = document.documentElement.clientWidth
  138. if (clientWidth < 1400)
  139. setSearchBoxCanAnimate(false)
  140. else
  141. setSearchBoxCanAnimate(true)
  142. }
  143. }, [searchBoxAutoAnimate])
  144. useEffect(() => {
  145. handleSearchBoxCanAnimateChange()
  146. }, [handleSearchBoxCanAnimateChange])
  147. useEffect(() => {
  148. window.addEventListener('resize', handleSearchBoxCanAnimateChange)
  149. return () => {
  150. window.removeEventListener('resize', handleSearchBoxCanAnimateChange)
  151. }
  152. }, [handleSearchBoxCanAnimateChange])
  153. return {
  154. searchBoxCanAnimate,
  155. }
  156. }