| 31 | ) => mixed, |
| 32 | }; |
| 33 | class APIRequestHandler extends React.PureComponent<Props> { |
| 34 | static isConnected(props: Props, request?: APIRequest): boolean { |
| 35 | const { inflightRequests, connection } = props; |
| 36 | if (!inflightRequests) { |
| 37 | return false; |
| 38 | } |
| 39 | // This is a hack. We actually have a race condition between |
| 40 | // ActivityHandler and Socket. Both of them respond to a backgrounding, but |
| 41 | // we want ActivityHandler to go first. Once it sends its message, Socket |
| 42 | // will wait for the response before shutting down. But if Socket starts |
| 43 | // shutting down first, we'll have a problem. Note that this approach only |
| 44 | // stops the race in fetchResponse below, and not in action-utils (which |
| 45 | // happens earlier via the registerActiveSocket call below), but empirically |
| 46 | // that hasn't been an issue. |
| 47 | // The reason I didn't rewrite this to happen in a single component is |
| 48 | // because I want to maintain separation of concerns. Upcoming React Hooks |
| 49 | // will be a great way to rewrite them to be related but still separated. |
| 50 | return ( |
| 51 | connection.status === 'connected' || |
| 52 | request?.endpoint === 'update_activity' |
| 53 | ); |
| 54 | } |
| 55 | |
| 56 | get registeredResponseFetcher(): ?SocketAPIHandler { |
| 57 | return APIRequestHandler.isConnected(this.props) |
| 58 | ? this.fetchResponse |
| 59 | : null; |
| 60 | } |
| 61 | |
| 62 | componentDidMount() { |
| 63 | this.props.registerActiveSocket( |
| 64 | this.props.keyserverID, |
| 65 | this.registeredResponseFetcher, |
| 66 | ); |
| 67 | } |
| 68 | |
| 69 | componentWillUnmount() { |
| 70 | this.props.registerActiveSocket(this.props.keyserverID, null); |
| 71 | } |
| 72 | |
| 73 | componentDidUpdate(prevProps: Props) { |
| 74 | const isConnected = APIRequestHandler.isConnected(this.props); |
| 75 | const wasConnected = APIRequestHandler.isConnected(prevProps); |
| 76 | if (isConnected !== wasConnected) { |
| 77 | this.props.registerActiveSocket( |
| 78 | this.props.keyserverID, |
| 79 | this.registeredResponseFetcher, |
| 80 | ); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | render(): React.Node { |
| 85 | return null; |
| 86 | } |
| 87 | |
| 88 | fetchResponse = async (request: APIRequest): Promise<mixed> => { |
| 89 | if (!APIRequestHandler.isConnected(this.props, request)) { |
| 90 | throw new SocketOffline('socket_offline'); |
nothing calls this directly
no test coverage detected