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.8KB

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