import App from './App.vue' import store from './store' import i18n from './plugins/lang'; import router from './router' import matrix from './services/matrix.service' import navigation from './services/navigation.service' import config from './services/config.service' import analytics from './services/analytics.service' import audioPlayer from './services/audio.service'; import 'roboto-fontface/css/roboto/roboto-fontface.css' import 'material-design-icons-iconfont/dist/material-design-icons.css' import VueResize from 'vue3-resize'; import 'vue3-resize/dist/vue3-resize.css'; import VueClipboard from 'vue-clipboard2' import Vue3Sanitize from "vue-3-sanitize"; import vuetify from './plugins/vuetify'; import { Buffer } from 'buffer/' import { createApp, h } from 'vue'; globalThis.Buffer = Buffer; var defaultOptions = Vue3Sanitize.defaults; defaultOptions.disallowedTagsMode = "recursiveEscape"; defaultOptions.allowedTags = []; const app = createApp({ render: () => h(App) }); app.use(Vue3Sanitize, defaultOptions); app.config.productionTip = false app.use(VueResize); const configLoadedPromise = new Promise((resolve, ignoredreject) => { // eslint-disable-next-line app.use(config, globalThis.window.location.origin, (config) => { resolve(config); }); // Use this before cleaninsights below, it depends on config! }); app.use(analytics); app.use(VueClipboard); app.use(audioPlayer); // Register a global custom directive called `v-blur` that prevents focus app.directive('blur', { mounted: function (el) { el.onfocus = (ev) => ev.target.blur() } }); /** * Handle long taps. Call with the timeout as argument (default 500ms) and the value * can be either one function called on long tap or two functions, the * first called on "short tap" and the other on "long tap". * * Like this: v-linkTap:500="[tapped,longTapped]" */ app.directive('longTap', { beforeMount: function (el, binding, ignoredvnode) { el.longTapTimeout = parseInt(binding.arg || "500"); el.longTapCallbacks = binding.value; for (var i = el.longTapCallbacks.length; i < 2; i++) { el.longTapCallbacks.splice(0, 0, null); } const touchX = function (event) { if (event.type.indexOf("mouse") !== -1) { return event.clientX; } return event.touches[0].clientX; }; const touchY = function (event) { if (event.type.indexOf("mouse") !== -1) { return event.clientY; } return event.touches[0].clientY; }; /** * Triggered when our "long tap" timer hits. */ const touchTimerElapsed = function () { el.longTapHandled = true; el.longTapCallbacks[1] && el.longTapCallbacks[1].call(el, el); el.longTapTimer = null; el.classList.remove("waiting-for-long-tap"); }; const touchStart = function (e) { el.longTapHandled = false; el.longTapStartX = touchX(e); el.longTapStartY = touchY(e); el.longTapTimer = setTimeout(touchTimerElapsed, el.longTapTimeout); el.classList.add("waiting-for-long-tap"); e.preventDefault(); }; const touchCancel = function () { el.longTapHandled = true; el.longTapTimer && clearTimeout(el.longTapTimer); el.longTapTimer = null; el.classList.remove("waiting-for-long-tap"); }; const touchEnd = function () { el.longTapTimer && clearTimeout(el.longTapTimer); el.longTapTimer = null; if (!el.longTapHandled) { // Not canceled or long tapped. Just a single tap. Do we have a handler? el.longTapCallbacks[0] && el.longTapCallbacks[0].call(el, el); } el.classList.remove("waiting-for-long-tap"); }; const touchMove = function (e) { el.longTapCurrentX = touchX(e); el.longTapCurrentY = touchY(e); var tapTolerance = 4; var touchMoved = Math.abs(el.longTapStartX - el.longTapCurrentX) > tapTolerance || Math.abs(el.longTapStartY - el.longTapCurrentY) > tapTolerance; if (touchMoved) { touchCancel(); } }; el.longTapTouchStart = touchStart; el.longTapTouchEnd = touchEnd; el.longTapTouchCancel = touchCancel; el.longTapTouchMove = touchMove; el.addEventListener("touchstart", touchStart); el.addEventListener("touchend", touchEnd); el.addEventListener("touchcancel", touchCancel); el.addEventListener("touchmove", touchMove); el.addEventListener("mousedown", touchStart); el.addEventListener("mouseup", touchEnd); el.addEventListener("mousemove", touchMove); }, unmounted: function (el) { el.longTapTimer && clearTimeout(el.longTapTimer); el.removeEventListener("touchstart", el.longTapTouchStart); el.removeEventListener("touchend", el.longTapTouchEnd); el.removeEventListener("touchcancel", el.longTapTouchCancel); el.removeEventListener("touchmove", el.longTapTouchMove); el.removeEventListener("mousedown", el.longTapTouchStart); el.removeEventListener("mouseup", el.longTapTouchEnd); el.removeEventListener("mousemove", el.longTapTouchMove); }, }); app.use(store); app.$store = store; app.config.globalProperties.$store = store; app.use(router); router.app = app; app.use(navigation, router); app.use(vuetify); app.use(i18n); app.$i18n = i18n; app.config.globalProperties.$i18n = i18n; app.provide("globalT", i18n.global.t); app.provide("globalSanitize", app.config.globalProperties.$sanitize); app.use(matrix, { store: store, i18n: i18n }); // Set $matrix inside data store store.$matrix = app.$matrix; if (app.$config.accentColor) { app.$vuetify.theme.themes.light.primary = app.$config.accentColor; } app.$audioPlayer.$root = app; // Make sure a $root is available here configLoadedPromise.then((config) => { if (config.accentColor) { app.$vuetify.theme.themes.light.primary = config.accentColor; } app.mount('#app'); });