AppMobile.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { onBeforeUnmount, onMounted, watch } from 'vue'
  4. import { useRouter } from 'vue-router'
  5. import CommonImageViewer from '#shared/components/CommonImageViewer/CommonImageViewer.vue'
  6. import CommonNotifications from '#shared/components/CommonNotifications/CommonNotifications.vue'
  7. import DynamicInitializer from '#shared/components/DynamicInitializer/DynamicInitializer.vue'
  8. import useAuthenticationChanges from '#shared/composables/authentication/useAuthenticationUpdates.ts'
  9. import useFormKitConfig from '#shared/composables/form/useFormKitConfig.ts'
  10. import useAppMaintenanceCheck from '#shared/composables/useAppMaintenanceCheck.ts'
  11. import useMetaTitle from '#shared/composables/useMetaTitle.ts'
  12. import usePushMessages from '#shared/composables/usePushMessages.ts'
  13. import { initializeDefaultObjectAttributes } from '#shared/entities/object-attributes/composables/useObjectAttributes.ts'
  14. import { useApplicationStore } from '#shared/stores/application.ts'
  15. import { useAuthenticationStore } from '#shared/stores/authentication.ts'
  16. import { useLocaleStore } from '#shared/stores/locale.ts'
  17. import { useSessionStore } from '#shared/stores/session.ts'
  18. import { registerSW } from '#shared/sw/register.ts'
  19. import emitter from '#shared/utils/emitter.ts'
  20. import CommonConfirmation from '#mobile/components/CommonConfirmation/CommonConfirmation.vue'
  21. import { useTicketOverviewsStore } from './entities/ticket/stores/ticketOverviews.ts'
  22. const router = useRouter()
  23. const authentication = useAuthenticationStore()
  24. const session = useSessionStore()
  25. useMetaTitle().initializeMetaTitle()
  26. const application = useApplicationStore()
  27. onMounted(() => {
  28. // If Zammad was not properly set up yet, redirect to desktop front end.
  29. if (!application.config.system_init_done) {
  30. window.location.pathname = '/'
  31. } else {
  32. application.setLoaded()
  33. }
  34. })
  35. const updateServiceWorker = registerSW({
  36. path: '/mobile/sw.js',
  37. scope: '/mobile/',
  38. })
  39. useAppMaintenanceCheck({ onNeedRefresh: () => updateServiceWorker(true) })
  40. usePushMessages()
  41. // Add a check for authenticated changes (e.g. login/logout in a other
  42. // browser tab or maintenance mode switch).
  43. useAuthenticationChanges()
  44. // We need to trigger a manual translation update for the form related strings.
  45. const formConfig = useFormKitConfig()
  46. useLocaleStore().$subscribe(() => {
  47. formConfig.locale = 'staticLocale'
  48. })
  49. // The handling for invalid sessions. The event will be emitted, when from the server a "NotAuthorized"
  50. // response is received.
  51. emitter.on('sessionInvalid', async () => {
  52. if (authentication.authenticated) {
  53. await authentication.clearAuthentication()
  54. router.replace({
  55. name: 'Login',
  56. query: {
  57. invalidatedSession: '1',
  58. },
  59. })
  60. }
  61. })
  62. // Initialize the ticket overview store after a valid session is present on
  63. // the app level, so that the query keeps alive.
  64. watch(
  65. () => session.initialized,
  66. (newValue, oldValue) => {
  67. if (!newValue || oldValue) return
  68. useTicketOverviewsStore()
  69. initializeDefaultObjectAttributes()
  70. },
  71. { immediate: true },
  72. )
  73. onBeforeUnmount(() => {
  74. emitter.off('sessionInvalid')
  75. })
  76. // Do not animate transitions in the test mode.
  77. const transition = VITE_TEST_MODE
  78. ? undefined
  79. : {
  80. enterActiveClass: 'duration-300 ease-out',
  81. enterFromClass: 'opacity-0 translate-y-3/4',
  82. enterToClass: 'opacity-100 translate-y-0',
  83. leaveActiveClass: 'duration-200 ease-in',
  84. leaveFromClass: 'opacity-100 translate-y-0',
  85. leaveToClass: 'opacity-0 translate-y-3/4',
  86. }
  87. </script>
  88. <template>
  89. <template v-if="application.loaded">
  90. <CommonNotifications />
  91. <CommonConfirmation />
  92. <Teleport to="body">
  93. <CommonImageViewer />
  94. </Teleport>
  95. </template>
  96. <div
  97. v-if="application.loaded"
  98. class="h-full min-w-full bg-black font-sans text-sm text-white antialiased"
  99. >
  100. <RouterView />
  101. </div>
  102. <DynamicInitializer name="dialog" :transition="transition" />
  103. </template>