mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-26 14:32:04 -04:00
181 lines
5.2 KiB
Vue
181 lines
5.2 KiB
Vue
<script setup lang="ts">
|
|
import sorter from 'avris-sorter';
|
|
import md5 from 'js-md5';
|
|
import { useCookie } from 'nuxt/app';
|
|
|
|
import useConfig from '~/composables/useConfig.ts';
|
|
import useDark from '~/composables/useDark.ts';
|
|
import useDialogue from '~/composables/useDialogue.ts';
|
|
import { longtimeCookieSetting } from '~/src/cookieSettings.ts';
|
|
import { LoadScriptError } from '~/src/errors.ts';
|
|
import { newDate } from '~/src/helpers.ts';
|
|
import { useMainStore } from '~/store/index.ts';
|
|
|
|
// no need to be super secure, just a sign that the page is not public
|
|
const TESTER_PASSWORD_HASH = '82feeb96d60170e714df8fb062301e90';
|
|
|
|
declare global {
|
|
interface Window {
|
|
dataLayer: unknown[];
|
|
}
|
|
}
|
|
|
|
const { $translator: translator, $isGranted: isGranted, $locales: locales, $loadScript: loadScript } = useNuxtApp();
|
|
const config = useConfig();
|
|
const runtimeConfig = useRuntimeConfig();
|
|
|
|
const store = useMainStore();
|
|
|
|
useDark();
|
|
|
|
const testerPasswordCookie = useCookie('tester-password', longtimeCookieSetting);
|
|
const testerPassword = ref('');
|
|
|
|
const requiresLogin = computed((): boolean => {
|
|
return !config.macrolanguage?.enabled && (runtimeConfig.public.env === 'test' ||
|
|
config.locale !== '_' && !locales[config.locale]?.published);
|
|
});
|
|
const testerPasswordValid = computed((): boolean => {
|
|
return !!testerPasswordCookie.value && md5(testerPasswordCookie.value) === TESTER_PASSWORD_HASH;
|
|
});
|
|
const checkTesterPassword = (): void => {
|
|
testerPasswordCookie.value = testerPassword.value;
|
|
};
|
|
|
|
onMounted(() => {
|
|
sorter();
|
|
|
|
confirmAge();
|
|
|
|
loadAds();
|
|
loadGTM();
|
|
|
|
let needsRefresh = false;
|
|
const bc = new BroadcastChannel('account_switch');
|
|
bc.onmessage = (ev): void => {
|
|
if (ev.data !== store.user?.username) {
|
|
needsRefresh = true;
|
|
if (document.hasFocus()) {
|
|
needsRefresh = false;
|
|
window.location.reload();
|
|
}
|
|
}
|
|
};
|
|
window.onfocus = (): void => {
|
|
if (needsRefresh) {
|
|
needsRefresh = false;
|
|
window.location.reload();
|
|
}
|
|
};
|
|
});
|
|
|
|
const dialogue = useDialogue();
|
|
const confirmAge = async (): Promise<void> => {
|
|
if (!translator.has('footer.ageLimit') || localStorage.getItem('ageConfirmed')) {
|
|
return;
|
|
}
|
|
|
|
await dialogue.alert(translator.translate('footer.ageLimit'));
|
|
|
|
localStorage.setItem('ageConfirmed', '1');
|
|
};
|
|
|
|
const adsEnabled = computed((): boolean => {
|
|
if (isGranted()) {
|
|
const adsVisible = parseInt(localStorage.getItem('adsVisible') || '0') === 1;
|
|
if (!adsVisible) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return !!config.ads?.enabled && import.meta.env?.APP_ENV === 'production';
|
|
});
|
|
const loadAds = async (): Promise<void> => {
|
|
if (!adsEnabled.value) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await loadScript(
|
|
'publift',
|
|
'https://cdn.fuseplatform.net/publift/tags/2/3329/fuse.js',
|
|
);
|
|
await loadScript(
|
|
'publift-video',
|
|
'https://live.primis.tech/live/liveView.php?s=118558&schain=1.0,1!publift.com,[01H9H7XDCTSKKX1ECPR1VWQXQ9],1',
|
|
undefined,
|
|
'[data-phkey=content-0]',
|
|
);
|
|
} catch (error) {
|
|
if (error instanceof LoadScriptError) {
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
const loadGTM = async (): Promise<void> => {
|
|
if (!adsEnabled.value) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await loadScript('gtm', 'https://www.googletagmanager.com/gtag/js?id=G-TDJEP12Q3M');
|
|
} catch (error) {
|
|
if (error instanceof LoadScriptError) {
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(...args: unknown[]): void {
|
|
window.dataLayer.push(args);
|
|
}
|
|
gtag('js', newDate());
|
|
gtag('config', 'G-TDJEP12Q3M');
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="requiresLogin && !testerPasswordValid" class="body">
|
|
<div class="container">
|
|
<div class="alert alert-warning m-3 text-center">
|
|
<Icon v="exclamation-triangle" />
|
|
This is a test server
|
|
</div>
|
|
<div class="m-3">
|
|
<div class="input-group py-1">
|
|
<input v-model="testerPassword" class="form-control" type="password" placeholder="Password" @keydown.enter.prevent="checkTesterPassword">
|
|
<button type="button" class="btn btn-primary btn-sm border" @click.prevent="checkTesterPassword">
|
|
<Icon v="sign-in" />
|
|
Sign in
|
|
</button>
|
|
</div>
|
|
<p v-if="testerPasswordCookie && !testerPasswordValid" class="small text-danger">
|
|
<Icon v="exclamation-triangle" />
|
|
Password invalid
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="body">
|
|
<div class="flex-grow-1 vh">
|
|
<Header />
|
|
<slot></slot>
|
|
<TranslationMode />
|
|
<ScrollButton />
|
|
</div>
|
|
<Footer />
|
|
<Lightbox />
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
@import "assets/variables";
|
|
@import "~avris-sorter/dist/Sorter.min.css";
|
|
|
|
.vh {
|
|
min-height: calc(100vh - #{$header-height});
|
|
}
|
|
</style>
|