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

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. updateShareCode(shareCode)
  62. const { isFetching, data: accessModeResult } = useGetWebAppAccessModeByCode(shareCode)
  63. const [isFetchingAccessToken, setIsFetchingAccessToken] = useState(false)
  64. useEffect(() => {
  65. if (accessModeResult?.accessMode) {
  66. updateWebAppAccessMode(accessModeResult.accessMode)
  67. if (accessModeResult.accessMode === AccessMode.PUBLIC) {
  68. setIsFetchingAccessToken(true)
  69. checkOrSetAccessToken(shareCode).finally(() => {
  70. setIsFetchingAccessToken(false)
  71. })
  72. }
  73. else {
  74. setIsFetchingAccessToken(false)
  75. }
  76. }
  77. }, [accessModeResult, updateWebAppAccessMode, shareCode])
  78. if (isFetching || isFetchingAccessToken) {
  79. return <div className='flex h-full w-full items-center justify-center'>
  80. <Loading />
  81. </div>
  82. }
  83. return (
  84. <>
  85. {children}
  86. </>
  87. )
  88. }
  89. export default WebAppStoreProvider