Ariver
2026-07-13 490d60bbc90a4f407d2d9111e0da70e7efe6995a
C1.source/privatevoice.src/frontend/src/App.svelte
@@ -19,24 +19,26 @@
  let showOnboarding = $state(false)
  onMount(() => {
    const offEvents: Array<() => void> = []
    Call.ByName('voicesnap/services.ConfigService.GetLanguageSettings').then((settings: any) => {
      applyLanguageSettings(settings)
    }).catch(() => {
      languageReady = true
    })
    Events.On('indicator:show', (ev: any) => {
    offEvents.push(Events.On('indicator:show', (ev: any) => {
      indicatorVisible.set(true)
      if (ev?.data?.status) {
        indicatorStatus.set(ev.data.status)
      }
    })
    }))
    Events.On('indicator:hide', () => {
    offEvents.push(Events.On('indicator:hide', () => {
      indicatorVisible.set(false)
    })
    }))
    Events.On('indicator:status', (ev: any) => {
    offEvents.push(Events.On('indicator:status', (ev: any) => {
      const data = ev?.data
      if (data?.status) {
        indicatorStatus.set(data.status)
@@ -44,13 +46,13 @@
      if (data?.hotkeyName) {
        hotkeyName.set(data.hotkeyName)
      }
    })
    }))
    Events.On('indicator:volume', (ev: any) => {
    offEvents.push(Events.On('indicator:volume', (ev: any) => {
      indicatorVolume.set(ev?.data ?? 0)
    })
    }))
    Events.On('engine:status', (ev: any) => {
    offEvents.push(Events.On('engine:status', (ev: any) => {
      const data = ev?.data
      if (data?.status) {
        engineStatus.set(data.status as any)
@@ -61,23 +63,24 @@
      if (data?.hardwareInfo) {
        engineHardwareInfo.set(data.hardwareInfo)
      }
    })
    }))
    Events.On('device:changed', (ev: any) => {
    offEvents.push(Events.On('device:changed', (ev: any) => {
      if (ev?.data?.name) {
        deviceName.set(ev.data.name)
      }
    })
    }))
    Events.On('update:available', (ev: any) => {
    offEvents.push(Events.On('update:available', (ev: any) => {
      const data = ev?.data as UpdateInfo
      updateAvailable.set(data)
      showUpdateDialog = true
    })
    }))
    window.addEventListener('hashchange', () => {
    const onHashChange = () => {
      isIndicatorRoute = window.location.hash === '#/indicator'
    })
    }
    window.addEventListener('hashchange', onHashChange)
    // Query engine status on mount (events emitted before frontend load are lost)
    Call.ByName('voicesnap/services.EngineService.GetStatus').then((data: any) => {
@@ -100,6 +103,11 @@
        hotkeyName.set(name)
      }
    })
    return () => {
      for (const off of offEvents) off()
      window.removeEventListener('hashchange', onHashChange)
    }
  })
  function applyLanguageSettings(settings: any) {