keanu-weblite/src/main.js
2025-11-05 17:31:43 +01:00

187 lines
6 KiB
JavaScript

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.ts'
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';
import { supportedImageTypes, supportedAvatarImageTypes } from '@/plugins/utils';
globalThis.Buffer = Buffer;
var defaultOptions = Vue3Sanitize.defaults;
defaultOptions.disallowedTagsMode = "recursiveEscape";
defaultOptions.allowedTags = [];
const app = createApp({
render: () => h(App)
});
app.config.globalProperties.supportedImageTypes = supportedImageTypes;
app.config.globalProperties.supportedAvatarImageTypes = supportedAvatarImageTypes;
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');
});