mirror of https://github.com/jetkvm/kvm.git
fix: resolve activity tracking and UI race conditions
- Remove LastActive reset on emergency promotion to preserve actual activity state - Fix UI rejection count race by tracking whether rejection was already counted - Optimize browser detection to avoid redundant string searches
This commit is contained in:
parent
587f8b5e4c
commit
79b5ec3e29
|
|
@ -1226,10 +1226,8 @@ func (sm *SessionManager) transferPrimaryRole(fromSessionID, toSessionID, transf
|
||||||
// Promote target session
|
// Promote target session
|
||||||
toSession.Mode = SessionModePrimary
|
toSession.Mode = SessionModePrimary
|
||||||
toSession.hidRPCAvailable = false
|
toSession.hidRPCAvailable = false
|
||||||
// Reset LastActive for all emergency promotions to prevent immediate re-timeout
|
// For manual transfers, preserve the session's actual LastActive timestamp
|
||||||
if strings.HasPrefix(transferType, "emergency_") {
|
// Emergency promotions inherit the observer's activity state - no free time
|
||||||
toSession.LastActive = time.Now()
|
|
||||||
}
|
|
||||||
sm.primarySessionID = toSessionID
|
sm.primarySessionID = toSessionID
|
||||||
|
|
||||||
// ALWAYS set lastPrimaryID to the new primary to support WebRTC reconnections
|
// ALWAYS set lastPrimaryID to the new primary to support WebRTC reconnections
|
||||||
|
|
@ -1476,16 +1474,19 @@ func extractBrowserFromUserAgent(userAgent string) *string {
|
||||||
ua := strings.ToLower(userAgent)
|
ua := strings.ToLower(userAgent)
|
||||||
|
|
||||||
// Check for common browsers (order matters - Chrome contains Safari, etc.)
|
// Check for common browsers (order matters - Chrome contains Safari, etc.)
|
||||||
|
// Optimize Safari check by caching Chrome detection
|
||||||
|
hasChrome := strings.Contains(ua, "chrome")
|
||||||
|
|
||||||
if strings.Contains(ua, "edg/") || strings.Contains(ua, "edge") {
|
if strings.Contains(ua, "edg/") || strings.Contains(ua, "edge") {
|
||||||
return &BrowserEdge
|
return &BrowserEdge
|
||||||
}
|
}
|
||||||
if strings.Contains(ua, "firefox") {
|
if strings.Contains(ua, "firefox") {
|
||||||
return &BrowserFirefox
|
return &BrowserFirefox
|
||||||
}
|
}
|
||||||
if strings.Contains(ua, "chrome") {
|
if hasChrome {
|
||||||
return &BrowserChrome
|
return &BrowserChrome
|
||||||
}
|
}
|
||||||
if strings.Contains(ua, "safari") && !strings.Contains(ua, "chrome") {
|
if strings.Contains(ua, "safari") {
|
||||||
return &BrowserSafari
|
return &BrowserSafari
|
||||||
}
|
}
|
||||||
if strings.Contains(ua, "opera") || strings.Contains(ua, "opr/") {
|
if strings.Contains(ua, "opera") || strings.Contains(ua, "opr/") {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState, useCallback, useRef } from "react";
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
import { XCircleIcon } from "@heroicons/react/24/outline";
|
import { XCircleIcon } from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
|
|
@ -30,6 +30,7 @@ export default function AccessDeniedOverlay({
|
||||||
const { maxRejectionAttempts } = useSettingsStore();
|
const { maxRejectionAttempts } = useSettingsStore();
|
||||||
const [countdown, setCountdown] = useState(10);
|
const [countdown, setCountdown] = useState(10);
|
||||||
const [isRetrying, setIsRetrying] = useState(false);
|
const [isRetrying, setIsRetrying] = useState(false);
|
||||||
|
const hasCountedRef = useRef(false);
|
||||||
|
|
||||||
const handleLogout = useCallback(async () => {
|
const handleLogout = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -50,7 +51,15 @@ export default function AccessDeniedOverlay({
|
||||||
}, [navigate, setUser, clearSession, clearNickname]);
|
}, [navigate, setUser, clearSession, clearNickname]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!show) return;
|
if (!show) {
|
||||||
|
hasCountedRef.current = false;
|
||||||
|
setCountdown(10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only count rejection once per showing
|
||||||
|
if (hasCountedRef.current) return;
|
||||||
|
hasCountedRef.current = true;
|
||||||
|
|
||||||
const newCount = incrementRejectionCount();
|
const newCount = incrementRejectionCount();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue