Replace hardcoded RGB values with var(--color-champagne-*) references
so the light theme respects admin-configured colors (background, surface,
text). Add !important to override inline styles from applyThemeColors.
Update card/glass/input/button overrides to use champagne-50 (dynamic
surface color) instead of hardcoded white.
Instead of manually overriding each bg-dark-*/border-dark-* opacity
variant with !important rules, swap the entire dark palette CSS
variables to champagne equivalents in .light scope. This automatically
handles all opacity variants, hover states, borders across all pages
without needing individual class overrides for each combination.
Instead of generating color stops from accent at fixed intensities,
use the actual background, surface and accent colors from theme settings.
This ensures Aurora properly adapts to both dark and light themes.
Add sun/moon toggle button to the desktop navigation bar so theme
switching is available in web version. Sync theme state across multiple
useTheme() instances via custom DOM event to avoid requiring page reload.
Aurora WebGL всегда использовала darkBackground для color stops,
при переключении на светлую тему фон анимации оставался тёмным.
Добавлен useTheme() для реактивного определения текущей темы,
background выбирается между darkBackground и lightBackground.
При HMR Vite перевыполняет main.tsx, вызывая повторный init() и mount*()
компонентов SDK. mountThemeParams() и другие бросают ConcurrentCallError
асинхронно, что не ловится синхронным try/catch.
Решение: флаг на window.__tg_sdk_initialized предотвращает повторную
инициализацию при горячей перезагрузке модуля.
- Обернуть каждый mount-вызов в safeMountSync() для защиты от
ConcurrentCallError при HMR/повторной инициализации
- Перенести requestFullscreen() внутрь mountViewport().then() — fullscreen
требует смонтированный viewport, ранее вызывался через dynamic import
с setTimeout до завершения mount
- Стабилизировать обработчик BackButton через useRef + useCallback —
navigate меняется каждый рендер, что вызывало постоянную
пере-подписку и потерю обработчика
Полный переход с нативного window.Telegram.WebApp API на @telegram-apps/sdk-react v3.
Bridge SDK оборачивал receiveEvent, из-за чего popup_closed не доходил до нативного
обработчика — это было основной причиной бага с двойным открытием попапа.
Изменения:
- Удалён @telegram-apps/react-router-integration (привязан к SDK v1)
- Инициализация SDK v3 в main.tsx: init(), restoreInitData(), mount всех компонентов
- AppWithNavigator: убран TelegramRouter (initNavigator + useIntegration), все платформы
на BrowserRouter, добавлен TelegramBackButton через SDK v3
- useTelegramSDK: детекция через retrieveLaunchParams(), реактивные значения через
useSignal() (fullscreen, viewport, safe area insets), initData через retrieveRawInitData()
- TelegramAdapter: полная перезапись — попапы через showPopup() (Promise-based, без
ручного onEvent/offEvent/timeout), кнопки через setMainButtonParams/showBackButton,
haptic через hapticFeedbackImpactOccurred, тема через themeParamsState с конвертацией
camelCase→snake_case, cloud storage через getCloudStorageItem/setCloudStorageItem
- api/client.ts: initData через retrieveRawInitData() вместо window.Telegram.WebApp.initData
- AppHeader: фото пользователя через initDataUser() сигнал
- ConnectionModal: openLink через SDK вместо window.Telegram.WebApp.openLink
- ColorPicker: детекция Telegram через isInTelegramWebApp()
- Удалён интерфейс TelegramWebApp (368 строк) и Window augmentation из vite-env.d.ts
- Убрано поле telegram из PlatformContext в types.ts
- Обновлён manualChunks в vite.config.ts
- Add persistent popupClosed listener that resets state even after
per-call listener is removed by timeout
- Increase safety timeout from 5s to 30s to give user time to interact
- On WebAppPopupOpened error, keep popupOpen=true to block retries
instead of resetting and allowing infinite error loop
- Remove callback param from showPopup to avoid dual-listener conflicts
- Remove debug console logs
Listen for popupClosed event as backup and add safety timeout
to handle Telegram Desktop bug where popup_closed payload is
undefined, preventing the callback from being invoked and
leaving popup state permanently locked.
Telegram may reinitialize window.Telegram.WebApp after app startup,
making cached references stale. Get a fresh reference inside
showPopupSafe to ensure the callback is registered on the current
WebApp instance.
Add popup guard in TelegramAdapter DialogController to prevent
"Popup is already opened" error. Migrate PromoOffersSection from
direct showPopup call to useDestructiveConfirm hook.
Replace manual BackButton management with official @telegram-apps/react-router-integration
to fix navigation issues (back button cycling and double-click).
Changes:
- Migrate from @tma.js/sdk-react to @telegram-apps/sdk-react
- Downgrade react-router-dom to v6 for package compatibility
- Add AppWithNavigator component with Telegram navigator integration
- Use browser history mode (hashMode: null) to prevent hash URLs
- Add multi-level platform detection (user data, platform, version)
- Add try-catch error handling for navigator attach/detach
- Simplify useBackButton hook to no-op (navigator handles automatically)
- Update vite config with new Telegram packages
The navigator automatically manages BackButton based on router history,
falling back to BrowserRouter in regular browser environment.
Fixed issue where users had to click the Telegram Mini App back button twice
in many admin pages. The replace flag was causing conflicts between Telegram's
BackButton internal history and React Router's history management.
Updated all 32 admin pages to use simple navigate() calls without replace flag.
Add replace: true to all navigate() calls in useBackButton hooks
Prevents history cycles when navigating back and forth
All 32 admin pages now use navigate(path, { replace: true })
Back button now goes directly to parent without cycling
Main sections navigate to /admin (15 pages)
Detail/edit pages navigate to parent lists (16 pages)
All pages use useBackButton hook with proper navigation paths
Native Telegram back button in Mini App, UI button on web
Email template pages keep UI-only back buttons as required
Replace desktop-style back button with native Telegram BackButton API:
- Use useBackButton hook for Telegram Mini App
- Show UI back button only on web (when !capabilities.hasBackButton)
- Improves native feel in Telegram environment
Payment methods drag-and-drop fixes:
- Restore original working drag-and-drop from commit 84c6d26
- Use position: relative instead of opacity for dragged items
- Remove closestCenter collision detection
- Use PointerSensor with distance: 5 without TouchSensor
- Restore touch-none and responsive padding on drag handles
- Restore original shadow and background colors
Promo deactivation feature:
- Add deactivation button to active discount banner in PromoOffersSection
- Use Telegram native popup (showPopup) in Mini App environment
- Fallback to modal for web browsers
- Add confirmation modal with warning about permanent action
- Integrate with useTelegramSDK for proper platform detection
Refactor to resolve react-refresh/only-export-components warnings:
- Move buttonVariants export to separate file (Button.variants.ts)
- Extract WebSocketContext to dedicated context file
- Move useWebSocketContext hook to separate file
- Update imports across affected files
All component files now export only components, improving fast refresh reliability
- Replace modal with dedicated AdminPaymentMethodEdit page
- Add route /admin/payment-methods/:methodId/edit
- Fix 401 error handling for auth endpoints to show error messages instead of reloading page
- Update client.ts to use window.Telegram.WebApp.initData directly
- Maintain useTelegramDnd for drag and drop functionality