You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

web-app-context.tsx 3.7KB

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