The conditional Telegram SDK loading (commit 4606ba2) caused dark mode to
break in non-Telegram browsers. Added dark mode CSS variable overrides with
proper fallbacks, and restored the module-level applyTheme() call that applies
theme before React renders, preventing a flash of incorrect styling.
- web/src/index.css: Added dark mode overrides for primary colors (--app-bg,
--app-fg, --app-hint, --app-link, --app-button, --app-button-text,
--app-secondary-bg) with system-appropriate dark fallbacks when Telegram
theme variables are unavailable
- web/src/hooks/useTheme.ts: Restored module-level applyTheme(currentScheme)
call to ensure theme is applied before React renders
Add lazy loading of Telegram SDK only when running inside Telegram Mini App
environment instead of unconditionally loading in all browsers. Includes:
- New environment detection functions: isTelegramEnvironment(), isTelegramApp()
- Dynamic SDK loading with 3s timeout via loadTelegramSdk()
- Removed static script tag from index.html
- Made haptic feedback lazy (SDK check on each call)
- Made theme listeners lazy (attached in initializeTheme())
- Updated all components to use unified detection functions
This prevents SDK load time overhead in regular browser environments while
ensuring the app works correctly both in Telegram and browser contexts.
Remove unreliable conditions from Telegram environment detection in useAuthSource:
- window.Telegram !== undefined: Always true due to unconditional SDK loading
- window.self !== window.top: Causes false positives in iframe scenarios
Only keep URL parameter detection (tgWebApp in search/hash) which is reliable.
This prevents 5-second polling delay before login page displays on PC browser.
- Add iOS Safari install prompt with step-by-step modal guide
- Fix Telegram environment detection (check initData, not just SDK presence)
- Fix install prompt re-entrancy issue (clear deferredPrompt immediately)
- Extract icon components to separate file (web/src/components/icons.tsx)
- Rename "Happy App" to "Hapi" throughout the UI and manifests
- Change button/icon colors from blue (--app-button) to neutral theme (--app-fg/--app-bg)
- Add install dismiss state to prevent repeated prompts
- Improve iOS Safari detection with robust user agent parsing
Add complete PWA implementation including service worker registration,
offline support, and installation prompts:
- Add vite-plugin-pwa and workbox-window dependencies for PWA tooling
- Configure VitePWA plugin with web app manifest and app metadata
- Set up Workbox caching strategies for API endpoints and CDN assets
- Implement service worker auto-update with user-triggered refresh
- Create usePWAInstall hook to handle beforeinstallprompt events
- Create useOnlineStatus hook for monitoring network connectivity
- Add InstallPrompt component with haptic feedback integration
- Add OfflineBanner component to notify users of offline status
- Configure PWA icons and assets (64x64, 192x192, 512x512 variants)
- Add TypeScript type declarations for virtual PWA register module
- Integrate PWA components and service worker into App.tsx and main.tsx
- Add PWA meta tags and viewport configuration to index.html
Replace no-op browser haptic feedback with Web Vibration API support,
allowing haptic feedback when running outside Telegram Mini App. Also
remove stale react-syntax-highlighter type reference from tsconfig.
Enable the web client to run in plain browser environments alongside Telegram Mini App support:
- Server: Add CLI_API_TOKEN authentication path as alternative to Telegram initData
- Client: Add useAuthSource hook to detect and manage Telegram vs browser auth sources
- Client: Add usePlatform hook for platform abstraction with graceful haptic feedback degradation
- Client: Add LoginPrompt component for browser access token login
- Client: Extend useTheme to fall back to system prefers-color-scheme in browser
- Client: Migrate all direct HapticFeedback calls to use usePlatform hook
Extract word detection and suggestion logic into reusable utilities and hooks.
Add FloatingOverlay and Autocomplete components for intelligent input assistance.
Integrate settings panel and abort button directly into ChatInput component.
Simplify SessionHeader by removing settings dialog (now in ChatInput).