main.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. 'use strict'
  2. import 'picocrank/styles.css'
  3. import 'femtocrank/dark.css'
  4. import './style.css'
  5. import 'iconify-icon'
  6. import { createClient } from '@connectrpc/connect'
  7. import { createConnectTransport } from '@connectrpc/connect-web'
  8. import { OliveTinApiService } from './resources/scripts/gen/olivetin/api/v1/olivetin_pb'
  9. import { createApp, h } from 'vue'
  10. import { createI18n } from 'vue-i18n'
  11. import router from './resources/vue/router.js'
  12. import App from './resources/vue/App.vue'
  13. import { initWebsocket } from './js/websocket.js'
  14. import { getSelectedLocale, loadInitialMessages } from './resources/vue/i18n.js'
  15. import { applyThemeStyles, getStoredThemePreference } from './resources/vue/utils/themeLoader.js'
  16. async function initClient () {
  17. const transport = createConnectTransport({
  18. baseUrl: window.location.protocol + '//' + window.location.host + '/api/'
  19. })
  20. const locale = getSelectedLocale()
  21. window.client = createClient(OliveTinApiService, transport)
  22. const [initResponse, messages] = await Promise.all([
  23. window.client.init({}),
  24. loadInitialMessages(locale)
  25. ])
  26. window.initResponse = initResponse
  27. if (window.initResponse.enableCustomJs) {
  28. const script = document.createElement('script')
  29. script.src = '/custom-webui/custom.js'
  30. script.async = true
  31. script.id = 'olivetin-custom-js'
  32. document.head.appendChild(script)
  33. }
  34. const i18nSettings = createI18n({
  35. legacy: false,
  36. locale,
  37. fallbackLocale: 'en',
  38. messages,
  39. postTranslation: (translated) => {
  40. const params = new URLSearchParams(window.location.search)
  41. if (params.has('debug-translations')) {
  42. return '____'
  43. } else {
  44. return translated
  45. }
  46. }
  47. })
  48. return i18nSettings
  49. }
  50. function setupVue (i18nSettings) {
  51. const app = createApp(App)
  52. app.use(router)
  53. app.use(i18nSettings)
  54. window.i18n = i18nSettings.global
  55. app.mount('#app')
  56. }
  57. function setupErrorDisplay (errorMessage) {
  58. const ErrorApp = {
  59. render () {
  60. return h('section', { class: 'bad', style: 'padding: 2em; text-align: center; margin: 2em auto;' }, [
  61. h('h2', 'OliveTin Init Failed'),
  62. h('p', errorMessage),
  63. h('p', 'Please check your browser console for more details.')
  64. ])
  65. }
  66. }
  67. const app = createApp(ErrorApp)
  68. app.mount('#app')
  69. }
  70. async function main () {
  71. try {
  72. const i18nSettings = await initClient()
  73. try {
  74. await applyThemeStyles(getStoredThemePreference())
  75. } catch (err) {
  76. console.warn('Failed to load theme CSS:', err)
  77. }
  78. initWebsocket()
  79. setupVue(i18nSettings)
  80. } catch (err) {
  81. const errorMessage = err.message || 'Failed to initialize. Please check your configuration and try again.'
  82. console.error('Init failed:', err)
  83. setupErrorDisplay(errorMessage)
  84. }
  85. }
  86. main()