<commit_before><template>
  <div id="top" />
  <NavBar @menuInteraction="updateHideScrollBar" />
  <div v-if="appLoading" class="app-container">
    <div class="app-loading">
      <Loader />
    </div>
  </div>
  <div v-else class="app-container" :class="{ 'hide-scroll': hideScrollBar }">
    <router-view v-if="appConfig" />
    <NoConfig v-else />
  </div>
  <div class="container scroll">
    <div
      class="scroll-button"
      :class="{ 'display-button': displayScrollButton }"
      @click="scrollToTop"
    >
      <i class="fa fa-chevron-up" aria-hidden="true"></i>
    </div>
  </div>
  <Footer
    v-if="appConfig"
    :version="appConfig ? appConfig.version : ''"
    :adminContact="appConfig.admin_contact"
  />
</template>

<script setup lang="ts">
  import { ComputedRef, computed, ref, onBeforeMount, onMounted } from 'vue'

  import Footer from '@/components/Footer.vue'
  import NavBar from '@/components/NavBar.vue'
  import NoConfig from '@/components/NoConfig.vue'
  import { ROOT_STORE } from '@/store/constants'
  import { TAppConfig } from '@/types/application'
  import { useStore } from '@/use/useStore'

  const store = useStore()

  const appConfig: ComputedRef<TAppConfig> = computed(
    () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
  )
  const appLoading: ComputedRef<boolean> = computed(
    () => store.getters[ROOT_STORE.GETTERS.APP_LOADING]
  )
  const hideScrollBar = ref(false)
  const displayScrollButton = ref(false)

  onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_CONFIG))
  onMounted(() => scroll())

  function updateHideScrollBar(isMenuOpen: boolean) {
    hideScrollBar.value = isMenuOpen
  }
  function isScrolledToBottom(element: Element): boolean {
    return (
      element.getBoundingClientRect().top < window.innerHeight &&
      element.getBoundingClientRect().bottom >= 0
    )
  }
  function scroll() {
    window.onscroll = () => {
      const bottom = document.querySelector('#bottom')
      displayScrollButton.value = bottom !== null && isScrolledToBottom(bottom)
    }
  }
  function scrollToTop() {
    window.scrollTo({
      top: 0,
      behavior: 'smooth',
    })
    setTimeout(() => {
      displayScrollButton.value = false
    }, 300)
  }
</script>

<style lang="scss">
  @import '~@/scss/base.scss';<commit_msg>Client - detect navigator language on startup<commit_after><template>
  <div id="top" />
  <NavBar @menuInteraction="updateHideScrollBar" />
  <div v-if="appLoading" class="app-container">
    <div class="app-loading">
      <Loader />
    </div>
  </div>
  <div v-else class="app-container" :class="{ 'hide-scroll': hideScrollBar }">
    <router-view v-if="appConfig" />
    <NoConfig v-else />
  </div>
  <div class="container scroll">
    <div
      class="scroll-button"
      :class="{ 'display-button': displayScrollButton }"
      @click="scrollToTop"
    >
      <i class="fa fa-chevron-up" aria-hidden="true"></i>
    </div>
  </div>
  <Footer
    v-if="appConfig"
    :version="appConfig ? appConfig.version : ''"
    :adminContact="appConfig.admin_contact"
  />
</template>

<script setup lang="ts">
  import { ComputedRef, computed, ref, onBeforeMount, onMounted } from 'vue'

  import Footer from '@/components/Footer.vue'
  import NavBar from '@/components/NavBar.vue'
  import NoConfig from '@/components/NoConfig.vue'
  import { ROOT_STORE } from '@/store/constants'
  import { TAppConfig } from '@/types/application'
  import { useStore } from '@/use/useStore'
  import { localeFromLanguage } from '@/utils/locales'

  const store = useStore()

  const appConfig: ComputedRef<TAppConfig> = computed(
    () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
  )
  const appLoading: ComputedRef<boolean> = computed(
    () => store.getters[ROOT_STORE.GETTERS.APP_LOADING]
  )
  const hideScrollBar = ref(false)
  const displayScrollButton = ref(false)

  onBeforeMount(() => {
    initLanguage()
    store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_CONFIG)
  })
  onMounted(() => scroll())

  function updateHideScrollBar(isMenuOpen: boolean) {
    hideScrollBar.value = isMenuOpen
  }
  function isScrolledToBottom(element: Element): boolean {
    return (
      element.getBoundingClientRect().top < window.innerHeight &&
      element.getBoundingClientRect().bottom >= 0
    )
  }
  function scroll() {
    window.onscroll = () => {
      const bottom = document.querySelector('#bottom')
      displayScrollButton.value = bottom !== null && isScrolledToBottom(bottom)
    }
  }
  function scrollToTop() {
    window.scrollTo({
      top: 0,
      behavior: 'smooth',
    })
    setTimeout(() => {
      displayScrollButton.value = false
    }, 300)
  }
  function initLanguage() {
    let language = 'en'
    try {
      const navigatorLanguage = navigator.language.split('-')[0]
      if (navigatorLanguage in localeFromLanguage) {
        language = navigatorLanguage
      }
    } catch (e) {
      language = 'en'
    }
    store.dispatch(ROOT_STORE.ACTIONS.UPDATE_APPLICATION_LANGUAGE, language)
  }
</script>

<style lang="scss">
  @import '~@/scss/base.scss';
{'fraction_non_alphanumeric': 0.1484896037661828, 'fraction_numerical': 0.0021577089054531187, 'mean_word_length': 3.488556338028169, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 67, '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': '2108577', 'n_tokens_mistral': 1679, 'n_tokens_neox': 1651, 'n_words': 316}