<commit_before>import axios from 'axios'
import classNames from 'classnames'
import {collapsedInitial, mapSettings, overrideParams, storeCollapsed, storeMapSettings} from './settings'
import {createMap, panTo, showRadarFrame} from './map'
import {Frame} from './types'
import {InfoPanel} from './info-panel'
import React, {useCallback, useEffect, useRef, useState} from 'react'
import ReactDOM from 'react-dom'
import {Timeline} from './timeline'

const FRAME_DELAY_MS = 500
const FRAME_LIST_RELOAD_MS = 30 * 1000

const map = createMap(mapSettings)
map.on('moveend', () => storeMapSettings(map.getView().getCenter(), map.getView().getZoom()))

if (!overrideParams.x && !overrideParams.y && navigator.geolocation) {
  navigator.geolocation.getCurrentPosition((position) => panTo(map, [position.coords.longitude, position.coords.latitude]))
}

// eslint-disable-next-line max-statements
function SataakoApp() {
  const mapRef = useRef<HTMLDivElement>(null)
  const [collapsed, setCollapsed] = useState<boolean>(collapsedInitial)
  const [currentTimestamp, setCurrentTimestamp] = useState<string|null>(null)
  const [frames, setFrames] = useState<Frame[]>([])
  const [running, setRunning] = useState<boolean>(true)
  const [frameDelay, setFrameDelay] = useState<number>(FRAME_DELAY_MS)

  useEffect(() => storeCollapsed(collapsed), [collapsed])
  useEffect(() => map.setTarget(mapRef.current ?? undefined), [])

  useEffect(() => {
    async function loadFramesList() {
      const {data}: {data: Frame[]} = await axios.get('/frames.json')
      setFrames(data)
      setCurrentTimestamp(currentTimestampDefault(currentTimestamp, data))
    }
    loadFramesList()
    const timer = setInterval(loadFramesList, FRAME_LIST_RELOAD_MS)
    return () => clearInterval(timer)
  }, [])

  useEffect(() => {
    function animateRadar() {
      setCurrentTimestamp(nextTimestamp(currentTimestamp, frames))
    }
    if (!running || !currentTimestamp) {
      return undefined
    }
    const timer = setInterval(animateRadar, frameDelay)
    return () => clearInterval(timer)
  }, [running, currentTimestamp, frameDelay])

  useEffect(() => {
    const currentFrame = frames.find(frame => frame.timestamp === currentTimestamp)
    if (currentFrame) {
      showRadarFrame(map, currentFrame)
      const isLastOfList = frames[frames.length - 1] === currentFrame
      if (isLastOfList) {
        setFrameDelay(5 * FRAME_DELAY_MS)
      } else if (currentFrame.isForecast) {
        setFrameDelay(3 * FRAME_DELAY_MS)
      } else {
        setFrameDelay(FRAME_DELAY_MS)
      }<commit_msg>A one-shot timeout will do, the hook is anyway triggered after each frame<commit_after>import axios from 'axios'
import classNames from 'classnames'
import {collapsedInitial, mapSettings, overrideParams, storeCollapsed, storeMapSettings} from './settings'
import {createMap, panTo, showRadarFrame} from './map'
import {Frame} from './types'
import {InfoPanel} from './info-panel'
import React, {useCallback, useEffect, useRef, useState} from 'react'
import ReactDOM from 'react-dom'
import {Timeline} from './timeline'

const FRAME_DELAY_MS = 500
const FRAME_LIST_RELOAD_MS = 30 * 1000

const map = createMap(mapSettings)
map.on('moveend', () => storeMapSettings(map.getView().getCenter(), map.getView().getZoom()))

if (!overrideParams.x && !overrideParams.y && navigator.geolocation) {
  navigator.geolocation.getCurrentPosition((position) => panTo(map, [position.coords.longitude, position.coords.latitude]))
}

// eslint-disable-next-line max-statements
function SataakoApp() {
  const mapRef = useRef<HTMLDivElement>(null)
  const [collapsed, setCollapsed] = useState<boolean>(collapsedInitial)
  const [currentTimestamp, setCurrentTimestamp] = useState<string|null>(null)
  const [frames, setFrames] = useState<Frame[]>([])
  const [running, setRunning] = useState<boolean>(true)
  const [frameDelay, setFrameDelay] = useState<number>(FRAME_DELAY_MS)

  useEffect(() => storeCollapsed(collapsed), [collapsed])
  useEffect(() => map.setTarget(mapRef.current ?? undefined), [])

  useEffect(() => {
    async function loadFramesList() {
      const {data}: {data: Frame[]} = await axios.get('/frames.json')
      setFrames(data)
      setCurrentTimestamp(currentTimestampDefault(currentTimestamp, data))
    }
    loadFramesList()
    const timer = setInterval(loadFramesList, FRAME_LIST_RELOAD_MS)
    return () => clearInterval(timer)
  }, [])

  useEffect(() => {
    function animateRadar() {
      setCurrentTimestamp(nextTimestamp(currentTimestamp, frames))
    }
    if (!running || !currentTimestamp) {
      return undefined
    }
    const timer = setTimeout(animateRadar, frameDelay)
    return () => clearTimeout(timer)
  }, [running, currentTimestamp, frameDelay])

  useEffect(() => {
    const currentFrame = frames.find(frame => frame.timestamp === currentTimestamp)
    if (currentFrame) {
      showRadarFrame(map, currentFrame)
      const isLastOfList = frames[frames.length - 1] === currentFrame
      if (isLastOfList) {
        setFrameDelay(5 * FRAME_DELAY_MS)
      } else if (currentFrame.isForecast) {
        setFrameDelay(3 * FRAME_DELAY_MS)
      } else {
        setFrameDelay(FRAME_DELAY_MS)
      }
{'fraction_non_alphanumeric': 0.13123561013046814, 'fraction_numerical': 0.004604758250191865, 'mean_word_length': 4.7665929203539825, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7180501', 'n_tokens_mistral': 1599, 'n_tokens_neox': 1558, 'n_words': 342}