Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default tseslint.config(
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-extraneous-class': 'off',
},
}
)
26 changes: 14 additions & 12 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { TanStackProvider, ThemeContext } from '@context'
import { ThemeContext } from '@context'
import '@styles/index.scss'
import { TonConnectUIProvider } from '@tonconnect/ui-react'
import { checkIsMobile, checkStartAppParams } from '@utils'

Check warning on line 4 in frontend/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint / lint

'checkIsMobile' is defined but never used
import { useContext, useEffect } from 'react'
import { useNavigate, useParams } from 'react-router-dom'

import config from '@config'
import { AuthService } from '@services'

Check warning on line 9 in frontend/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint / lint

'AuthService' is defined but never used
import { useUser, useUserActions } from '@store'
import { useAuthQuery } from '@store-new'

Check warning on line 11 in frontend/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint / lint

'useAuthQuery' is defined but never used

import Routes from './Routes'

Expand All @@ -17,6 +19,8 @@
const { darkTheme } = useContext(ThemeContext)
const navigate = useNavigate()

// useAuthQuery()

const { authenticateUserAction, fetchUserAction } = useUserActions()
const { isAuthenticated } = useUser()

Expand Down Expand Up @@ -90,19 +94,17 @@
}
}, [isAuthenticated])

if (!isAuthenticated) return null
// if (!AuthService.isAuth()) return null

return (
<TanStackProvider>
<TonConnectUIProvider
manifestUrl={config.tonConnectManifestUrl}
actionsConfiguration={{
twaReturnUrl: `https://t.me/${config.botName}/gate?startapp=ch_${clientChatSlug}`,
}}
>
{Routes}
</TonConnectUIProvider>
</TanStackProvider>
<TonConnectUIProvider
manifestUrl={config.tonConnectManifestUrl}
actionsConfiguration={{
twaReturnUrl: `https://t.me/${config.botName}/gate?startapp=ch_${clientChatSlug}`,
}}
>
{Routes}
</TonConnectUIProvider>
)
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/common/hooks/useClipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
export function useClipboard() {
const { showToast } = useToast()

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

return {
copy: (text: string, message: string) => {
webApp.HapticFeedback.notificationOccurred('success')
webApp?.HapticFeedback.notificationOccurred('success')
navigator.clipboard
.writeText(text.toString())
.then(() => {
showToast({ message, type: 'copy', time: 2000 })
})
.catch((err) => {

Check warning on line 16 in frontend/src/common/hooks/useClipboard.ts

View workflow job for this annotation

GitHub Actions / lint / lint

'err' is defined but never used
showToast({ type: 'error', message: 'Unable to copy' })
})
},
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/common/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { ChatsPopularSortBy } from '@types'
import { ChatsPopularOrderBy } from '@types'

export const API_VALIDATION_ERROR = 'Fill fields correctly'

export const API_ERRORS = {}

export const TANSTACK_KEYS = {
CHATS_POPULAR: (sortBy: ChatsPopularSortBy) => ['chats', 'popular', sortBy],
AUTH: ['auth'],
USER: ['user'],
CHATS_POPULAR: (sortBy: ChatsPopularOrderBy) => ['chats', 'popular', sortBy],
CHAT: (slug: string) => ['chat', slug],
ADMIN_CHATS: ['admin', 'chats'],
}

export const TANSTACK_TTL = {
AUTH: 5 * 60 * 1000, // 5 minute
USER: 1 * 60 * 1000, // 1 minute
CHATS_POPULAR: 5 * 60 * 1000, // 5 minute
ADMIN_CHATS: 5 * 60 * 1000, // 5 minute
CHAT: 5 * 60 * 1000, // 5 minute
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/common/utils/goTo.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const goTo = (link: string) => {
const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

if (link.includes('t.me')) {
webApp.openTelegramLink(link)
webApp?.openTelegramLink(link)
} else {
webApp.openLink(link)
webApp?.openLink(link)
}
}
1 change: 1 addition & 0 deletions frontend/src/common/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './createMembersCount'
export * from './createConditionDescription'
export * from './checkIsMobile'
export * from './hapticFeedback'
export * from './pluralize'
17 changes: 17 additions & 0 deletions frontend/src/common/utils/pluralize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const pluralize = (
textForms: [string, string, string], // [one, few, many]
multiplier: number // number of items
): string => {
const mod10 = multiplier % 10
const mod100 = multiplier % 100

const prettifiedMultiplier = multiplier.toLocaleString()

if (mod10 === 1 && mod100 !== 11) {
return `${prettifiedMultiplier} ${textForms[0]}`
}
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {
return `${prettifiedMultiplier} ${textForms[1]}`
}
return `${prettifiedMultiplier} ${textForms[2]}`
}
3 changes: 3 additions & 0 deletions frontend/src/components/BlockNew/BlockNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import cn from 'classnames'
import styles from './BlockNew.module.scss'

interface BlockNewProps {
id?: string
children: React.ReactNode
margin?: string
defaultWidth?: boolean
Expand Down Expand Up @@ -50,6 +51,7 @@ interface BlockNewProps {
}

export const BlockNew = ({
id,
children,
fixed,
row,
Expand All @@ -65,6 +67,7 @@ export const BlockNew = ({
}: BlockNewProps) => {
return (
<div
id={id}
onClick={onClick}
style={{
padding,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ListToggler/ListToggler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import cn from 'classnames'

import styles from './ListToggler.module.scss'

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

interface ListTogglerProps {
isEnabled: boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.root {
overflow-y: auto;
height: 100vh;
min-height: 100vh;
animation: fadeIn 0.3s ease-in-out;
padding: 16px 0;
overflow: hidden;
}

// .isMobile {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,19 @@ export const TelegramMainButton = memo(
}, [disabled, loading, text])

useEffect(() => {
if (webApp.MainButton && onClick) {
webApp.MainButton.onClick(onClick)
if (webApp?.MainButton && onClick) {
webApp?.MainButton.onClick(onClick)

return () => {
if (webApp.MainButton) {
webApp.MainButton.offClick(onClick)
if (webApp?.MainButton) {
webApp?.MainButton.offClick(onClick)
}
}
}
}, [onClick])

if (
webApp.platform === 'unknown' &&
webApp?.platform === 'unknown' &&
process.env.NODE_ENV !== 'production' &&
isVisible
) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/Toast/ToastElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ToastOptions {
| 'warning'
}

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

export const ToastElement = ({
children,
Expand Down Expand Up @@ -52,11 +52,11 @@ export const ToastElement = ({
useEffect(() => {
setTimeout(() => {
if (type === 'error') {
webApp.HapticFeedback.notificationOccurred('error')
webApp?.HapticFeedback.notificationOccurred('error')
}

if (type === 'success') {
webApp.HapticFeedback.notificationOccurred('success')
webApp?.HapticFeedback.notificationOccurred('success')
}
setIsOpen(true)
}, 50)
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/context/TanStackProvider/TanStackProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { useToast } from '@components'
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
import { QueryClient, QueryCache, MutationCache } from '@tanstack/react-query'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { API_ERRORS } from '@utils'
import { API_ERRORS, TANSTACK_KEYS } from '@utils'
import { PropsWithChildren, useMemo } from 'react'

import { AuthService } from '@services'

const HIDDEN_ERRORS = ['user_forbidden', 'synced_recently', 'TON_CONNECT']

export const TanStackProvider = (props: PropsWithChildren) => {
Expand Down Expand Up @@ -53,10 +55,19 @@ export const TanStackProvider = (props: PropsWithChildren) => {
retryOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
enabled: (query) => {
if (query.queryKey === TANSTACK_KEYS.AUTH) return true
return AuthService.isAuth()
},
},
mutations: {
retry: false,
throwOnError: false,
onMutate: () => {
if (!AuthService.isAuth()) {
throw new Error('Authorization required')
}
},
},
},
}),
Expand Down
18 changes: 10 additions & 8 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ToastProvider } from '@components'
import { ThemeProvider } from '@context'
import { TanStackProvider, ThemeProvider } from '@context'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
Expand All @@ -8,12 +8,14 @@ import App from './App'

createRoot(document.getElementById('root') as HTMLElement).render(
<StrictMode>
<BrowserRouter>
<ToastProvider>
<ThemeProvider>
<App />
</ThemeProvider>
</ToastProvider>
</BrowserRouter>
<TanStackProvider>
<BrowserRouter>
<ToastProvider>
<ThemeProvider>
<App />
</ThemeProvider>
</ToastProvider>
</BrowserRouter>
</TanStackProvider>
</StrictMode>
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { AdminChat, useChatActions } from '@store'

import { findNewChat } from './helpers'

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

export const AddBotToChatPage = () => {
const { appNavigate } = useAppNavigation()
Expand All @@ -39,7 +39,7 @@ export const AddBotToChatPage = () => {
}, [appNavigate])

const addGatewayBot = useCallback(() => {
webApp.openTelegramLink(
webApp?.openTelegramLink(
`${config.botLink}?startgroup=&admin=restrict_members+invite_users`
)
setIsCheckingNewChat(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useParams } from 'react-router-dom'

import { useChatActions, useApp, useAppActions } from '@store'

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

export const BotAddedSuccessPage = () => {
const { chatSlug } = useParams<{ chatSlug: string }>()
Expand All @@ -30,7 +30,7 @@ export const BotAddedSuccessPage = () => {
if (!chatSlug) return
try {
await fetchChatAction(chatSlug)
webApp.HapticFeedback.notificationOccurred('success')
webApp?.HapticFeedback.notificationOccurred('success')
} catch (error) {
console.error(error)
adminChatNotFound()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { DraggableCondition } from '../DraggableCondition'
import { DroppableGroup } from '../DroppableGroup'
import styles from './ChatConditions.module.scss'

const webApp = window.Telegram.WebApp
const webApp = window.Telegram?.WebApp

export const ChatConditions = () => {
const { appNavigate } = useAppNavigation()
Expand Down Expand Up @@ -69,7 +69,7 @@ export const ChatConditions = () => {
order: order,
chatSlug: chat?.slug || '',
})
webApp.HapticFeedback.impactOccurred('soft')
webApp?.HapticFeedback.impactOccurred('soft')
} catch (error) {
console.error(error)
showToast({
Expand Down Expand Up @@ -137,7 +137,7 @@ export const ChatConditions = () => {
const handleDragStart = (event: DragStartEvent) => {
if (!canDrag) return
setActiveId(event.active.id as string)
webApp.HapticFeedback.impactOccurred('light')
webApp?.HapticFeedback.impactOccurred('light')
}

const handleDragEnd = (event: DragEndEvent) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export const ChatHeader = () => {
const [description, setDescription] = useState(chat?.description ?? '')

const isMobile =
webApp.platform === 'ios' ||
webApp.platform === 'android' ||
webApp.platform === 'android_x'
webApp?.platform === 'ios' ||
webApp?.platform === 'android' ||
webApp?.platform === 'android_x'

const handleChangeDescription = (value: string) => {
setDescription(value)
Expand All @@ -40,12 +40,12 @@ export const ChatHeader = () => {

const handleShareLink = () => {
if (!chat?.slug) return
webApp.HapticFeedback.impactOccurred('soft')
webApp?.HapticFeedback.impactOccurred('soft')

const url = `${config.miniAppLink}?startapp=ch_${chat?.slug}`

if (isMobile) {
webApp.openTelegramLink(
webApp?.openTelegramLink(
`https://t.me/share/url?url=${encodeURI(url)}&text=${chat.title}`
)
} else {
Expand All @@ -56,7 +56,7 @@ export const ChatHeader = () => {
const handleCopyLink = () => {
if (!chat?.slug) return
const url = `${config.miniAppLink}?startapp=ch_${chat?.slug}`
webApp.HapticFeedback.impactOccurred('soft')
webApp?.HapticFeedback.impactOccurred('soft')
copy(url, 'Link copied!')
}

Expand Down
Loading
Loading