diff --git a/apps/app-frontend/index.html b/apps/app-frontend/index.html index 891f575f24..e5549f28ad 100644 --- a/apps/app-frontend/index.html +++ b/apps/app-frontend/index.html @@ -11,6 +11,7 @@
+ diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 6d2451c319..cb1ea25e46 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -18,12 +18,13 @@ import RunningAppBar from '@/components/ui/RunningAppBar.vue' import SplashScreen from '@/components/ui/SplashScreen.vue' import URLConfirmModal from '@/components/ui/URLConfirmModal.vue' import { useCheckDisableMouseover } from '@/composables/macCssFix.js' -import { hide_ads_window, init_ads_window } from '@/helpers/ads.js' +import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads.js' import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics' import { get_user } from '@/helpers/cache.js' import { command_listener, warning_listener } from '@/helpers/events.js' import { useFetch } from '@/helpers/fetch.js' import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.js' +import { list } from '@/helpers/profile.js' import { get } from '@/helpers/settings.ts' import { get_opening_command, initialize_state } from '@/helpers/state' import { getOS, isDev, restartApp } from '@/helpers/utils.js' @@ -43,6 +44,7 @@ import { MaximizeIcon, MinimizeIcon, NewspaperIcon, + NotepadTextIcon, PlusIcon, RestoreIcon, RightArrowIcon, @@ -67,6 +69,7 @@ import { openUrl } from '@tauri-apps/plugin-opener' import { type } from '@tauri-apps/plugin-os' import { check } from '@tauri-apps/plugin-updater' import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state' +import { $fetch } from 'ofetch' import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue' import { RouterView, useRoute, useRouter } from 'vue-router' import { create_profile_and_install_from_file } from './helpers/pack' @@ -81,6 +84,7 @@ provideNotificationManager(notificationManager) const { handleError, addNotification } = notificationManager const news = ref([]) +const availableSurvey = ref(false) const urlModal = ref(null) @@ -225,6 +229,12 @@ async function setupApp() { } catch (error) { console.warn('Failed to generate skin previews in app setup.', error) } + + if (osType === 'windows') { + await processPendingSurveys() + } else { + console.info('Skipping user surveys on non-Windows platforms') + } } const stateFailed = ref(false) @@ -412,6 +422,116 @@ function handleAuxClick(e) { e.target.dispatchEvent(event) } } + +function cleanupOldSurveyDisplayData() { + const threeWeeksAgo = new Date() + threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21) + + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i) + + if (key.startsWith('survey-') && key.endsWith('-display')) { + const dateValue = new Date(localStorage.getItem(key)) + if (dateValue < threeWeeksAgo) { + localStorage.removeItem(key) + } + } + } +} + +async function openSurvey() { + if (!availableSurvey.value) { + console.error('No survey to open') + return + } + + const creds = await getCreds().catch(handleError) + const userId = creds?.user_id + + const formId = availableSurvey.value.tally_id + + const popupOptions = { + layout: 'modal', + width: 700, + autoClose: 2000, + hideTitle: true, + hiddenFields: { + user_id: userId, + }, + onOpen: () => console.info('Opened user survey'), + onClose: () => { + console.info('Closed user survey') + show_ads_window() + }, + onSubmit: () => console.info('Active user survey submitted'), + } + + try { + hide_ads_window() + if (window.Tally?.openPopup) { + console.info(`Opening Tally popup for user survey (form ID: ${formId})`) + dismissSurvey() + window.Tally.openPopup(formId, popupOptions) + } else { + console.warn('Tally script not yet loaded') + show_ads_window() + } + } catch (e) { + console.error('Error opening Tally popup:', e) + show_ads_window() + } + + console.info(`Found user survey to show with tally_id: ${formId}`) + window.Tally.openPopup(formId, popupOptions) +} + +function dismissSurvey() { + localStorage.setItem(`survey-${availableSurvey.value.id}-display`, new Date()) + availableSurvey.value = undefined +} + +async function processPendingSurveys() { + function isWithinLastTwoWeeks(date) { + const twoWeeksAgo = new Date() + twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14) + return date >= twoWeeksAgo + } + + cleanupOldSurveyDisplayData() + + const creds = await getCreds().catch(handleError) + const userId = creds?.user_id + + const instances = await list().catch(handleError) + const isActivePlayer = + instances.findIndex( + (instance) => + isWithinLastTwoWeeks(instance.last_played) && !isWithinLastTwoWeeks(instance.created), + ) >= 0 + + let surveys = [] + try { + surveys = await $fetch('https://api.modrinth.com/v2/surveys') + } catch (e) { + console.error('Error fetching surveys:', e) + } + + const surveyToShow = surveys.find( + (survey) => + !!( + localStorage.getItem(`survey-${survey.id}-display`) === null && + survey.type === 'tally_app' && + ((survey.condition === 'active_player' && isActivePlayer) || + (survey.assigned_users?.includes(userId) && !survey.dismissed_users?.includes(userId))) + ), + ) + + if (surveyToShow) { + availableSurvey.value = surveyToShow + } else { + console.info('No user survey to show') + } +}