<commit_before>import ReconnectingWebsocket from 'reconnecting-websocket'
import { debounce } from 'quasar'

import store from '@/store'
import log from '@/services/log'
import auth from '@/services/api/auth'
import { getter } from '@/store/storeHelpers'

import { camelizeKeys } from '@/services/utils'
import { convert as convertApplication } from '@/services/api/groupApplications'
import { convert as convertMessage } from '@/services/api/messages'
import { convert as convertConversation } from '@/services/api/conversations'
import { convert as convertPickup } from '@/services/api/pickups'
import { convert as convertSeries } from '@/services/api/pickupSeries'
import { convert as convertFeedback } from '@/services/api/feedback'
import { convert as convertHistory } from '@/services/api/history'
import { convert as convertInvitation } from '@/services/api/invitations'
import { convert as convertGroup } from '@/services/api/groups'
import { convert as convertNotification, convertMeta as convertNotificationMeta } from '@/services/api/notifications'

let WEBSOCKET_ENDPOINT

if (__ENV.CORDOVA) {
  WEBSOCKET_ENDPOINT = [
    __ENV.BACKEND.replace(/^http/, 'ws'),
    '/api/ws',
  ].join('')
}
else {
  WEBSOCKET_ENDPOINT = [
    window.location.protocol.replace(/^http/, 'ws'),
    '//',
    window.location.host,
    '/api/ws',
  ].join('')
}

const options = {
  reconnectInterval: 500,
}

let ws, pingTimer, pingTimeout

const socket = {
  connect (protocols) {
    if (ws) return
    ws = new ReconnectingWebsocket(WEBSOCKET_ENDPOINT, protocols, options)

    const ping = () => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({ type: 'ping' }))
      }
      clearTimeout(pingTimeout)
      pingTimeout = setTimeout(() => {
        store.commit('connectivity/websocket', false)
      }, 2000)
    }

    pingTimer = setInterval(ping, 10000)

    ws.addEventListener('open', () => {
      ping()
      log.debug('socket opened!')
    })

    ws.addEventListener('close', () => {
      ping()
      log.debug('socket closed!')
    })

    ws.addEventListener('message', (event) => {
      let data
      try {
        data = JSON.parse(event.data)
      }
      catch (err) {
        log.error('socket message was not json', event.data)
        return
      }

      store.commit('connectivity/websocket', true)
      if (data.type && data.type === 'pong') {
        clearTimeout(pingTimeout)
      }

      receiveMessage(data)
    })

    function watchConnection () {
      // uses the draft Network Information API if available
      // https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
      const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
      if (!connection) return

      const debouncedReconnect = debounce(() => ws.reconnect(), 500)
      connection.addEventListener('change', () => {
        if (!store.getters['connectivity/websocket']) {
          debouncedReconnect()
        }
      })
    }

    watchConnection()
  },
  disconnect () {
    if (pingTimer) clearTimeout(pingTimer)
    if (ws) {
      ws.close(undefined, undefined, { keepClosed: true })
      ws = null
    }<commit_msg>ignore ping timeout when app is in background<commit_after>import ReconnectingWebsocket from 'reconnecting-websocket'
import { debounce, AppVisibility } from 'quasar'

import store from '@/store'
import log from '@/services/log'
import auth from '@/services/api/auth'
import { getter } from '@/store/storeHelpers'

import { camelizeKeys } from '@/services/utils'
import { convert as convertApplication } from '@/services/api/groupApplications'
import { convert as convertMessage } from '@/services/api/messages'
import { convert as convertConversation } from '@/services/api/conversations'
import { convert as convertPickup } from '@/services/api/pickups'
import { convert as convertSeries } from '@/services/api/pickupSeries'
import { convert as convertFeedback } from '@/services/api/feedback'
import { convert as convertHistory } from '@/services/api/history'
import { convert as convertInvitation } from '@/services/api/invitations'
import { convert as convertGroup } from '@/services/api/groups'
import { convert as convertNotification, convertMeta as convertNotificationMeta } from '@/services/api/notifications'

let WEBSOCKET_ENDPOINT

if (__ENV.CORDOVA) {
  WEBSOCKET_ENDPOINT = [
    __ENV.BACKEND.replace(/^http/, 'ws'),
    '/api/ws',
  ].join('')
}
else {
  WEBSOCKET_ENDPOINT = [
    window.location.protocol.replace(/^http/, 'ws'),
    '//',
    window.location.host,
    '/api/ws',
  ].join('')
}

const options = {
  reconnectInterval: 500,
}

let ws, pingTimer, pingTimeout

const ping = () => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: 'ping' }))
  }
  clearTimeout(pingTimeout)
  pingTimeout = setTimeout(() => {
    if (!AppVisibility.appVisible) return
    store.commit('connectivity/websocket', false)
  }, 2000)
}

const startPing = () => {
  ping()
  pingTimer = setInterval(ping, 10000)
}

const stopPing = () => {
  clearTimeout(pingTimeout)
  clearInterval(pingTimer)
}

const socket = {
  connect (protocols) {
    if (ws) return
    ws = new ReconnectingWebsocket(WEBSOCKET_ENDPOINT, protocols, options)

    ws.addEventListener('open', () => {
      // ping immediately if connection was opened
      // we need to stop existing pings beforehand to avoid overlap
      stopPing()
      startPing()
      log.debug('socket opened!')
    })

    ws.addEventListener('close', () => {
      // we check if we really lost the connection
      // maybe a new connection was opened before the old one was closed
      stopPing()
      startPing()
      log.debug('socket closed!')
    })

    ws.addEventListener('message', (event) => {
      let data
      try {
        data = JSON.parse(event.data)
      }
      catch (err) {
        log.error('socket message was not json', event.data)
        return
      }

      store.commit('connectivity/websocket', true)
      if (data.type && data.type === 'pong') {
        clearTimeout(pingTimeout)
      }

      receiveMessage(data)
    })

    function watchConnection () {
      const debouncedReconnect = debounce(() => ws.reconnect(), 500)

      // this should work in cordova, maybe
      document.addEventListener('online', () => {
        if (!store.getters['connectivity/websocket']) {
          debouncedReconnect()
        }
      })

      // this uses the draft Network Information API if available
      // https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
      const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
      if (!connection) return

      connection.addEventListener('change', () => {
        if (!store.getters['connectivity/websocket']) {
          debouncedReconnect()
        }
      })
    }

    watchConnection()
  },
  disconnect () {
    stopPing()
    if (ws) {
      ws.close(undefined, undefined, { keepClosed: true })
      ws = null
    }
{'fraction_non_alphanumeric': 0.13240073477462203, 'fraction_numerical': 0.00423908435777872, 'mean_word_length': 3.1295215869311552, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 20, 'https://': 2, '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': '6835223', 'n_tokens_mistral': 2156, 'n_tokens_neox': 2049, 'n_words': 499}