您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

web-app-context.tsx 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. 'use client'
  2. import type { ChatConfig } from '@/app/components/base/chat/types'
  3. import Loading from '@/app/components/base/loading'
  4. import { AccessMode } from '@/models/access-control'
  5. import type { AppData, AppMeta } from '@/models/share'
  6. import { useGetWebAppAccessModeByCode } from '@/service/use-share'
  7. import { usePathname, useSearchParams } from 'next/navigation'
  8. import type { FC, PropsWithChildren } from 'react'
  9. import { useEffect } from 'react'
  10. import { useState } from 'react'
  11. import { create } from 'zustand'
  12. type WebAppStore = {
  13. shareCode: string | null
  14. updateShareCode: (shareCode: string | null) => void
  15. appInfo: AppData | null
  16. updateAppInfo: (appInfo: AppData | null) => void
  17. appParams: ChatConfig | null
  18. updateAppParams: (appParams: ChatConfig | null) => void
  19. webAppAccessMode: AccessMode
  20. updateWebAppAccessMode: (accessMode: AccessMode) => void
  21. appMeta: AppMeta | null
  22. updateWebAppMeta: (appMeta: AppMeta | null) => void
  23. userCanAccessApp: boolean
  24. updateUserCanAccessApp: (canAccess: boolean) => void
  25. }
  26. export const useWebAppStore = create<WebAppStore>(set => ({
  27. shareCode: null,
  28. updateShareCode: (shareCode: string | null) => set(() => ({ shareCode })),
  29. appInfo: null,
  30. updateAppInfo: (appInfo: AppData | null) => set(() => ({ appInfo })),
  31. appParams: null,
  32. updateAppParams: (appParams: ChatConfig | null) => set(() => ({ appParams })),
  33. webAppAccessMode: AccessMode.SPECIFIC_GROUPS_MEMBERS,
  34. updateWebAppAccessMode: (accessMode: AccessMode) => set(() => ({ webAppAccessMode: accessMode })),
  35. appMeta: null,
  36. updateWebAppMeta: (appMeta: AppMeta | null) => set(() => ({ appMeta })),
  37. userCanAccessApp: false,
  38. updateUserCanAccessApp: (canAccess: boolean) => set(() => ({ userCanAccessApp: canAccess })),
  39. }))
  40. const getShareCodeFromRedirectUrl = (redirectUrl: string | null): string | null => {
  41. if (!redirectUrl || redirectUrl.length === 0)
  42. return null
  43. const url = new URL(`${window.location.origin}${decodeURIComponent(redirectUrl)}`)
  44. return url.pathname.split('/').pop() || null
  45. }
  46. const getShareCodeFromPathname = (pathname: string): string | null => {
  47. const code = pathname.split('/').pop() || null
  48. if (code === 'webapp-signin')
  49. return null
  50. return code
  51. }
  52. const WebAppStoreProvider: FC<PropsWithChildren> = ({ children }) => {
  53. const updateWebAppAccessMode = useWebAppStore(state => state.updateWebAppAccessMode)
  54. const updateShareCode = useWebAppStore(state => state.updateShareCode)
  55. const pathname = usePathname()
  56. const searchParams = useSearchParams()
  57. const redirectUrlParam = searchParams.get('redirect_url')
  58. const [shareCode, setShareCode] = useState<string | null>(null)
  59. useEffect(() => {
  60. const shareCodeFromRedirect = getShareCodeFromRedirectUrl(redirectUrlParam)
  61. const shareCodeFromPathname = getShareCodeFromPathname(pathname)
  62. const newShareCode = shareCodeFromRedirect || shareCodeFromPathname
  63. setShareCode(newShareCode)
  64. updateShareCode(newShareCode)
  65. }, [pathname, redirectUrlParam, updateShareCode])
  66. const { isFetching, data: accessModeResult } = useGetWebAppAccessModeByCode(shareCode)
  67. useEffect(() => {
  68. if (accessModeResult?.accessMode)
  69. updateWebAppAccessMode(accessModeResult.accessMode)
  70. }, [accessModeResult, updateWebAppAccessMode])
  71. if (isFetching) {
  72. return <div className='flex h-full w-full items-center justify-center'>
  73. <Loading />
  74. </div>
  75. }
  76. return (
  77. <>
  78. {children}
  79. </>
  80. )
  81. }
  82. export default WebAppStoreProvider