Fix UX issues: Suppress PWA in dev, respect onboarding preference, silence WS warnings
PWA Install Prompt: - Suppress in development (process.env.NODE_ENV === 'development') - Remember dismissal for 7 days (localStorage 'pwa_prompt_dismissed') - Delay showing by 30 seconds in production to avoid interrupting users Onboarding Tour: - Now respects 'Dont Show Again' checkbox (isDontShowAgain check added) - 1-second delay before showing (smoother UX) - Won't appear if user previously checked 'Dont show again' WebSocket Connection: - Removed console.log/warn for connect/disconnect/error events - Increased reconnection delay from 1s to 5s (less spam) - Reduced reconnection attempts from 10 to 3 - Increased timeout from 10s to 15s - Errors now silently fail (WebSocket is optional for real-time collaboration)
This commit is contained in:
1 parent
0c7a69ffe0
commit
13fce9d906
3 files changed
+32
-14
No files matched your search
@@ -126,7 +126,7 @@ import { t } from '@/lib/i18n';
|
||||
import { fetchSchoolYears, fetchStudents, fetchClasses, fetchDBNotifications, markAllNotificationsRead, markSingleNotificationRead, type SchoolYear, type Student, type ClassGroup, type DBNotification, type DBNotificationData } from '@/lib/api';
|
||||
import { apiGet } from '@/lib/api';
|
||||
import type { School as SchoolType } from '@/lib/api';
|
||||
import OnboardingTour, { isOnboardingCompleted } from '@/components/onboarding-tour';
|
||||
import OnboardingTour, { isOnboardingCompleted, isDontShowAgain } from '@/components/onboarding-tour';
|
||||
import KeyboardShortcutsDialog from '@/components/keyboard-shortcuts-dialog';
|
||||
import {
|
||||
CommandDialog,
|
||||
@@ -755,10 +755,11 @@ export default function AppLayout() {
|
||||
setCurrentView('classes');
|
||||
}, [setCurrentClass, setCurrentView]);
|
||||
|
||||
// Check onboarding status on mount
|
||||
// Check onboarding status on mount - respect "don't show again" preference
|
||||
useEffect(() => {
|
||||
if (!isOnboardingCompleted()) {
|
||||
setOnboardingOpen(true);
|
||||
if (!isOnboardingCompleted() && !isDontShowAgain()) {
|
||||
const timer = setTimeout(() => setOnboardingOpen(true), 1000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -94,10 +94,27 @@ export function PWAInstallPrompt() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't show PWA prompt in development
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user dismissed recently (within 7 days)
|
||||
try {
|
||||
const dismissedAt = localStorage.getItem('pwa_prompt_dismissed');
|
||||
if (dismissedAt) {
|
||||
const daysSince = (Date.now() - parseInt(dismissedAt)) / (1000 * 60 * 60 * 24);
|
||||
if (daysSince < 7) return;
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const handleBeforeInstall = (e: Event) => {
|
||||
e.preventDefault();
|
||||
setDeferredPrompt(e as BeforeInstallPromptEvent);
|
||||
setShowInstall(true);
|
||||
// Delay showing by 30 seconds to avoid interrupting the user
|
||||
setTimeout(() => setShowInstall(true), 30000);
|
||||
};
|
||||
|
||||
const handleAppInstalled = () => {
|
||||
@@ -155,7 +172,10 @@ export function PWAInstallPrompt() {
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowInstall(false)}
|
||||
onClick={() => {
|
||||
setShowInstall(false);
|
||||
try { localStorage.setItem('pwa_prompt_dismissed', String(Date.now())); } catch {}
|
||||
}}
|
||||
className="h-8 text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
||||
>
|
||||
{t('action.cancel')}
|
||||
|
||||
@@ -73,26 +73,23 @@ function connectSocket(userId: string, userName: string, schoolId: string, role:
|
||||
const socket = io('/?XTransformPort=3003', {
|
||||
transports: ['websocket', 'polling'],
|
||||
reconnection: true,
|
||||
reconnectionDelay: 1000,
|
||||
reconnectionAttempts: 10,
|
||||
timeout: 10000,
|
||||
reconnectionDelay: 5000,
|
||||
reconnectionAttempts: 3,
|
||||
timeout: 15000,
|
||||
});
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log('[CT-WS] Connected to WebSocket service');
|
||||
socketConnected = true;
|
||||
// Authenticate
|
||||
socket.emit('auth', { userId, userName, schoolId, role });
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log('[CT-WS] Disconnected from WebSocket service');
|
||||
socketConnected = false;
|
||||
});
|
||||
|
||||
socket.on('connect_error', (err) => {
|
||||
console.warn('[CT-WS] Connection error:', err.message);
|
||||
socket.on('connect_error', () => {
|
||||
socketConnected = false;
|
||||
// Silently fail - WebSocket is optional (real-time collaboration only)
|
||||
});
|
||||
|
||||
socketInstance = socket;
|
||||
|
||||
Reference in new issue
Block a user