diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index c961dda2a4..c85852fd5b 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -95,8 +95,9 @@ import { hide_ads_window, init_ads_window, perform_ads_consent_action, + release_ads_window_hold, should_show_ads_consent_popup, - show_ads_window, + take_ads_window_hold, } from '@/helpers/ads.js' import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics' import { check_reachable } from '@/helpers/auth.js' @@ -166,6 +167,25 @@ function updateHistoryNavigationState() { canNavigateForward.value = historyState?.forward != null } +let fullscreenAdsWindowHold = false + +async function handleFullscreenChange() { + const fullscreen = document.fullscreenElement !== null + if (fullscreen === fullscreenAdsWindowHold) return + + fullscreenAdsWindowHold = fullscreen + try { + if (fullscreen) { + await take_ads_window_hold() + } else { + await release_ads_window_hold() + } + } catch (error) { + fullscreenAdsWindowHold = !fullscreen + handleError(error) + } +} + updateHistoryNavigationState() const APP_LEFT_NAV_WIDTH = '4rem' @@ -284,8 +304,8 @@ providePageContext({ }) provideModalBehavior({ noblur: computed(() => !themeStore.advancedRendering), - onShow: () => hide_ads_window(), - onHide: () => show_ads_window(), + onShow: () => take_ads_window_hold(), + onHide: () => release_ads_window_hold(), }) const { @@ -360,6 +380,7 @@ onMounted(async () => { document.querySelector('body').addEventListener('click', handleClick) document.querySelector('body').addEventListener('auxclick', handleAuxClick) + document.addEventListener('fullscreenchange', handleFullscreenChange) checkUpdates() }) @@ -367,8 +388,13 @@ onMounted(async () => { onUnmounted(async () => { document.querySelector('body').removeEventListener('click', handleClick) document.querySelector('body').removeEventListener('auxclick', handleAuxClick) + document.removeEventListener('fullscreenchange', handleFullscreenChange) clearDelayedUpdatePopup() + if (fullscreenAdsWindowHold) { + fullscreenAdsWindowHold = false + await release_ads_window_hold().catch(handleError) + } await unlistenAdsConsent?.() await unlistenUpdateDownload?.() }) diff --git a/apps/app-frontend/src/components/ui/SurveyPopup.vue b/apps/app-frontend/src/components/ui/SurveyPopup.vue index 5199c000c9..7c2f4069b3 100644 --- a/apps/app-frontend/src/components/ui/SurveyPopup.vue +++ b/apps/app-frontend/src/components/ui/SurveyPopup.vue @@ -3,12 +3,14 @@ import { NotepadTextIcon, XIcon } from '@modrinth/assets' import { Button, defineMessages, injectNotificationManager, useVIntl } from '@modrinth/ui' import { type } from '@tauri-apps/plugin-os' import { $fetch } from 'ofetch' -import { onMounted, ref } from 'vue' +import { onMounted, onUnmounted, ref } from 'vue' -import { hide_ads_window, show_ads_window } from '@/helpers/ads.js' +import { release_ads_window_hold, take_ads_window_hold } from '@/helpers/ads.js' import { list } from '@/helpers/instance' import { get as getCreds } from '@/helpers/mr_auth.ts' +let adsWindowHold = false + type Survey = { id: string tally_id: string @@ -92,30 +94,44 @@ async function openSurvey() { onOpen: () => console.info('Opened user survey'), onClose: () => { console.info('Closed user survey') - show_ads_window() + if (adsWindowHold) { + adsWindowHold = false + release_ads_window_hold() + } }, onSubmit: () => console.info('Active user survey submitted'), } try { - hide_ads_window() + await take_ads_window_hold() + adsWindowHold = true if (tallyWindow.Tally?.openPopup) { console.info(`Opening Tally popup for user survey (form ID: ${formId})`) dismissSurvey() tallyWindow.Tally.openPopup(formId, popupOptions) } else { console.warn('Tally script not yet loaded') - show_ads_window() + adsWindowHold = false + await release_ads_window_hold() } } catch (e) { console.error('Error opening Tally popup:', e) - show_ads_window() + if (adsWindowHold) { + adsWindowHold = false + await release_ads_window_hold() + } } console.info(`Found user survey to show with tally_id: ${formId}`) - tallyWindow.Tally?.openPopup(formId, popupOptions) } +onUnmounted(() => { + if (adsWindowHold) { + adsWindowHold = false + release_ads_window_hold() + } +}) + function dismissSurvey() { if (!availableSurvey.value) return localStorage.setItem(`survey-${availableSurvey.value.id}-display`, String(new Date())) diff --git a/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue b/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue index a08649009f..9f29f9a945 100644 --- a/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue +++ b/apps/app-frontend/src/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue @@ -10,7 +10,6 @@ import { import { Admonition, Button, ButtonLink, Collapsible, IconButton, NewModal } from '@modrinth/ui' import { computed, ref } from 'vue' -import { hide_ads_window, show_ads_window } from '@/helpers/ads.js' import { login as login_flow, set_default_user } from '@/helpers/auth.js' import { handleSevereError } from '@/store/error.js' @@ -29,19 +28,13 @@ function show(errorVal: { message?: string }) { matchedError.value = findMinecraftAuthError(rawError.value) debugCollapsed.value = true - hide_ads_window() modal.value?.show() } function hide() { - onModalHide() modal.value?.hide() } -function onModalHide() { - show_ads_window() -} - defineExpose({ show, hide, @@ -74,7 +67,7 @@ async function copyToClipboard(text: string) {