hooks.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 } = 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. isLoading: isPending,
  98. }
  99. }
  100. export const useMixedTranslation = (localeFromOuter?: string) => {
  101. let t = useTranslation().t
  102. if (localeFromOuter)
  103. t = i18n.getFixedT(localeFromOuter)
  104. return {
  105. t,
  106. }
  107. }
  108. export const useMarketplaceContainerScroll = (
  109. callback: () => void,
  110. scrollContainerId = 'marketplace-container',
  111. ) => {
  112. const container = document.getElementById(scrollContainerId)
  113. const handleScroll = useCallback((e: Event) => {
  114. const target = e.target as HTMLDivElement
  115. const {
  116. scrollTop,
  117. scrollHeight,
  118. clientHeight,
  119. } = target
  120. if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0)
  121. callback()
  122. }, [callback])
  123. useEffect(() => {
  124. if (container)
  125. container.addEventListener('scroll', handleScroll)
  126. return () => {
  127. if (container)
  128. container.removeEventListener('scroll', handleScroll)
  129. }
  130. }, [container, handleScroll])
  131. }
  132. export const useSearchBoxAutoAnimate = (searchBoxAutoAnimate?: boolean) => {
  133. const [searchBoxCanAnimate, setSearchBoxCanAnimate] = useState(true)
  134. const handleSearchBoxCanAnimateChange = useCallback(() => {
  135. if (!searchBoxAutoAnimate) {
  136. const clientWidth = document.documentElement.clientWidth
  137. if (clientWidth < 1400)
  138. setSearchBoxCanAnimate(false)
  139. else
  140. setSearchBoxCanAnimate(true)
  141. }
  142. }, [searchBoxAutoAnimate])
  143. useEffect(() => {
  144. handleSearchBoxCanAnimateChange()
  145. }, [handleSearchBoxCanAnimateChange])
  146. useEffect(() => {
  147. window.addEventListener('resize', handleSearchBoxCanAnimateChange)
  148. return () => {
  149. window.removeEventListener('resize', handleSearchBoxCanAnimateChange)
  150. }
  151. }, [handleSearchBoxCanAnimateChange])
  152. return {
  153. searchBoxCanAnimate,
  154. }
  155. }