0

I am building a react-native / expo application that I am running as a web app. When I tab out of safari, and wait 10-15 seconds and tab back into it, my application is not consistently reconnecting to the websocket that it previously was connected to.

This issue is not consistent and I have tried to catch the document events to see what happens the times it does not trigger and I realised it is to do with the visibilitychange event not being called twice when this issue occurs. Instead it gets called once when the app is minimised and not again when you maximise safari (which makes the code not trigger).

Here is my code below which has my way of detecting all the different events and logging it.

I was wondering if anyone had experience building Expo apps and how they combatted IOS 16 so that they can consistently detect that safari has been minimised / maximised every time and not intermittently.

import { AppState, AppStateStatus, View } from 'react-native';
import LoginPage from './login';
import Header from '../components/Header';
import socket from '@/services/socketService';
import { useEffect, useState } from 'react';
import { Spinner } from '@gluestack-ui/themed';
import DeviceService from '@/services/deviceService';

socket

export default function Home() {
  const [isLoading, setLoading] = useState(false);

  useEffect(() => {
    const handleAppStateChange = (nextAppState: AppStateStatus) => {
      setLoading(true)
      if (nextAppState === 'active') {
        DeviceService.getGameState()
      } else if (nextAppState === 'background') {
        const currentTime = new Date();
        localStorage.setItem("lastBackgroundTime", currentTime.toString())
      }
      setLoading(false)
    };

    socket.emit('log', 'useEffectTriggered')

    const eventNames: any = [
      'load',
      'focus',
      'blur',
      'change',
      'close',
      'error',
      'haschange',
      'message',
      'offline',
      'online',
      'pagehide',
      'pageshow',
      'popstate',
      'resize',
      'submit',
      'unload',
      'beforeunload',
      'visibilitychange',
      'hidden',
      'visible',
      'webkitHidden'
    ];
    eventNames.forEach(function(eventName: any) {
      document.addEventListener(eventName, function(evt) {
        const now = new Date();
        const timeStr = now.getHours().toString().padStart(2, '0') + ':' +
          now.getMinutes().toString().padStart(2, '0') + ':' +
          now.getSeconds().toString().padStart(2, '0') + '.' +
          now.getMilliseconds();
          DeviceService.getGameState()
          const logString = eventName + ' ' + timeStr.toString() + evt

          socket.emit('log', logString)
      })})

    const subscription = AppState.addEventListener('change', handleAppStateChange);

    return () => {
      subscription.remove();
    };
  }, []);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Header fontSize={65} isBackEnabled={false}></Header>
      {isLoading
        ? <Spinner size="large" />
        : <LoginPage></LoginPage>
      }
    </View>
  );
}

I have currently tried to debug it all by logging all the events that are being called on the BE by emitting it via a socket. I have also tried to use EXPO's built in AppStateStatus which detects if the application is active or in background however that fails to detect it 100% of the time aswell.

I have also tried everything from this post which seems outdated here -> How to detect in iOS webapp when switching back to Safari from background?

Anyone got some other suggestions?

0