fix: hide ad webview when showing fullscreen content (#7110)

* fix: hide ad webview when showing fullscreen content

* fixes
This commit is contained in:
aecsocket
2026-08-12 16:02:02 +00:00
committed by GitHub
parent c34bd26f87
commit 6ec979a076
9 changed files with 186 additions and 171 deletions
+29 -3
View File
@@ -95,8 +95,9 @@ import {
hide_ads_window, hide_ads_window,
init_ads_window, init_ads_window,
perform_ads_consent_action, perform_ads_consent_action,
release_ads_window_hold,
should_show_ads_consent_popup, should_show_ads_consent_popup,
show_ads_window, take_ads_window_hold,
} from '@/helpers/ads.js' } from '@/helpers/ads.js'
import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics' import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics'
import { check_reachable } from '@/helpers/auth.js' import { check_reachable } from '@/helpers/auth.js'
@@ -166,6 +167,25 @@ function updateHistoryNavigationState() {
canNavigateForward.value = historyState?.forward != null 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() updateHistoryNavigationState()
const APP_LEFT_NAV_WIDTH = '4rem' const APP_LEFT_NAV_WIDTH = '4rem'
@@ -284,8 +304,8 @@ providePageContext({
}) })
provideModalBehavior({ provideModalBehavior({
noblur: computed(() => !themeStore.advancedRendering), noblur: computed(() => !themeStore.advancedRendering),
onShow: () => hide_ads_window(), onShow: () => take_ads_window_hold(),
onHide: () => show_ads_window(), onHide: () => release_ads_window_hold(),
}) })
const { const {
@@ -360,6 +380,7 @@ onMounted(async () => {
document.querySelector('body').addEventListener('click', handleClick) document.querySelector('body').addEventListener('click', handleClick)
document.querySelector('body').addEventListener('auxclick', handleAuxClick) document.querySelector('body').addEventListener('auxclick', handleAuxClick)
document.addEventListener('fullscreenchange', handleFullscreenChange)
checkUpdates() checkUpdates()
}) })
@@ -367,8 +388,13 @@ onMounted(async () => {
onUnmounted(async () => { onUnmounted(async () => {
document.querySelector('body').removeEventListener('click', handleClick) document.querySelector('body').removeEventListener('click', handleClick)
document.querySelector('body').removeEventListener('auxclick', handleAuxClick) document.querySelector('body').removeEventListener('auxclick', handleAuxClick)
document.removeEventListener('fullscreenchange', handleFullscreenChange)
clearDelayedUpdatePopup() clearDelayedUpdatePopup()
if (fullscreenAdsWindowHold) {
fullscreenAdsWindowHold = false
await release_ads_window_hold().catch(handleError)
}
await unlistenAdsConsent?.() await unlistenAdsConsent?.()
await unlistenUpdateDownload?.() await unlistenUpdateDownload?.()
}) })
@@ -3,12 +3,14 @@ import { NotepadTextIcon, XIcon } from '@modrinth/assets'
import { Button, defineMessages, injectNotificationManager, useVIntl } from '@modrinth/ui' import { Button, defineMessages, injectNotificationManager, useVIntl } from '@modrinth/ui'
import { type } from '@tauri-apps/plugin-os' import { type } from '@tauri-apps/plugin-os'
import { $fetch } from 'ofetch' 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 { list } from '@/helpers/instance'
import { get as getCreds } from '@/helpers/mr_auth.ts' import { get as getCreds } from '@/helpers/mr_auth.ts'
let adsWindowHold = false
type Survey = { type Survey = {
id: string id: string
tally_id: string tally_id: string
@@ -92,30 +94,44 @@ async function openSurvey() {
onOpen: () => console.info('Opened user survey'), onOpen: () => console.info('Opened user survey'),
onClose: () => { onClose: () => {
console.info('Closed user survey') console.info('Closed user survey')
show_ads_window() if (adsWindowHold) {
adsWindowHold = false
release_ads_window_hold()
}
}, },
onSubmit: () => console.info('Active user survey submitted'), onSubmit: () => console.info('Active user survey submitted'),
} }
try { try {
hide_ads_window() await take_ads_window_hold()
adsWindowHold = true
if (tallyWindow.Tally?.openPopup) { if (tallyWindow.Tally?.openPopup) {
console.info(`Opening Tally popup for user survey (form ID: ${formId})`) console.info(`Opening Tally popup for user survey (form ID: ${formId})`)
dismissSurvey() dismissSurvey()
tallyWindow.Tally.openPopup(formId, popupOptions) tallyWindow.Tally.openPopup(formId, popupOptions)
} else { } else {
console.warn('Tally script not yet loaded') console.warn('Tally script not yet loaded')
show_ads_window() adsWindowHold = false
await release_ads_window_hold()
} }
} catch (e) { } catch (e) {
console.error('Error opening Tally popup:', 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}`) 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() { function dismissSurvey() {
if (!availableSurvey.value) return if (!availableSurvey.value) return
localStorage.setItem(`survey-${availableSurvey.value.id}-display`, String(new Date())) localStorage.setItem(`survey-${availableSurvey.value.id}-display`, String(new Date()))
@@ -10,7 +10,6 @@ import {
import { Admonition, Button, ButtonLink, Collapsible, IconButton, NewModal } from '@modrinth/ui' import { Admonition, Button, ButtonLink, Collapsible, IconButton, NewModal } from '@modrinth/ui'
import { computed, ref } from 'vue' 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 { login as login_flow, set_default_user } from '@/helpers/auth.js'
import { handleSevereError } from '@/store/error.js' import { handleSevereError } from '@/store/error.js'
@@ -29,19 +28,13 @@ function show(errorVal: { message?: string }) {
matchedError.value = findMinecraftAuthError(rawError.value) matchedError.value = findMinecraftAuthError(rawError.value)
debugCollapsed.value = true debugCollapsed.value = true
hide_ads_window()
modal.value?.show() modal.value?.show()
} }
function hide() { function hide() {
onModalHide()
modal.value?.hide() modal.value?.hide()
} }
function onModalHide() {
show_ads_window()
}
defineExpose({ defineExpose({
show, show,
hide, hide,
@@ -74,7 +67,7 @@ async function copyToClipboard(text: string) {
</script> </script>
<template> <template>
<NewModal ref="modal" header="Sign in Failed" :max-width="'548px'" @hide="onModalHide"> <NewModal ref="modal" header="Sign in Failed" :max-width="'548px'">
<div class="flex flex-col gap-6"> <div class="flex flex-col gap-6">
<Admonition <Admonition
type="warning" type="warning"
@@ -3,7 +3,6 @@
ref="modal" ref="modal"
:header="formatMessage(messages.installToPlay)" :header="formatMessage(messages.installToPlay)"
:closable="true" :closable="true"
:on-hide="show_ads_window"
max-width="544px" max-width="544px"
width="544px" width="544px"
> >
@@ -169,7 +168,6 @@ import {
import { openUrl } from '@tauri-apps/plugin-opener' import { openUrl } from '@tauri-apps/plugin-opener'
import { computed, nextTick, ref } from 'vue' import { computed, nextTick, ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads'
import { get_project, get_project_many, get_version, get_version_many } from '@/helpers/cache.js' import { get_project, get_project_many, get_version, get_version_many } from '@/helpers/cache.js'
import { injectServerInstall } from '@/providers/server-install' import { injectServerInstall } from '@/providers/server-install'
@@ -352,7 +350,6 @@ async function show(
if (modpackVersionIdVal) await fetchData(modpackVersionIdVal) if (modpackVersionIdVal) await fetchData(modpackVersionIdVal)
hide_ads_window()
modal.value?.show(e) modal.value?.show(e)
await nextTick() await nextTick()
forceCheckTableScroll() forceCheckTableScroll()
@@ -268,7 +268,6 @@ import { openUrl } from '@tauri-apps/plugin-opener'
import { computed, nextTick, ref } from 'vue' import { computed, nextTick, ref } from 'vue'
import { config } from '@/config' import { config } from '@/config'
import { hide_ads_window, show_ads_window } from '@/helpers/ads'
import { toError } from '@/helpers/errors' import { toError } from '@/helpers/errors'
import type { SharedInstanceInstallPreview } from '@/helpers/install' import type { SharedInstanceInstallPreview } from '@/helpers/install'
import { create_report } from '@/helpers/reports' import { create_report } from '@/helpers/reports'
@@ -448,7 +447,6 @@ function handleCancel() {
function handleHide() { function handleHide() {
resetReportState() resetReportState()
creator.value = null creator.value = null
show_ads_window()
} }
function resetReportState() { function resetReportState() {
reportMode.value = false reportMode.value = false
@@ -488,7 +486,6 @@ function showReport(
} }
function showPreview(previewValue: SharedInstanceInstallPreview, event?: MouseEvent) { function showPreview(previewValue: SharedInstanceInstallPreview, event?: MouseEvent) {
preview.value = previewValue preview.value = previewValue
hide_ads_window()
modal.value?.show(event) modal.value?.show(event)
void nextTick(() => forceCheckTableScroll()) void nextTick(() => forceCheckTableScroll())
} }
+21 -2
View File
@@ -8,8 +8,27 @@ export async function init_ads_window(overrideShown = false) {
}) })
} }
export async function show_ads_window() { let adsWindowHoldUpdate = Promise.resolve()
return await invoke('plugin:ads|show_ads_window', { dpr: window.devicePixelRatio })
async function update_ads_window_hold(acquire) {
adsWindowHoldUpdate = adsWindowHoldUpdate
.catch(() => {})
.then(() =>
invoke('plugin:ads|update_ads_window_hold', {
acquire,
dpr: window.devicePixelRatio,
}),
)
return await adsWindowHoldUpdate
}
export async function take_ads_window_hold() {
return await update_ads_window_hold(true)
}
export async function release_ads_window_hold() {
return await update_ads_window_hold(false)
} }
export async function hide_ads_window(reset) { export async function hide_ads_window(reset) {
@@ -93,7 +93,7 @@ import {
import { ButtonLink, Card, IconButton, useFormatDateTime } from '@modrinth/ui' import { ButtonLink, Card, IconButton, useFormatDateTime } from '@modrinth/ui'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, 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 { trackEvent } from '@/helpers/analytics' import { trackEvent } from '@/helpers/analytics'
const MC_SERVER_BANNER_NAME = '__mc_server_banner__' const MC_SERVER_BANNER_NAME = '__mc_server_banner__'
@@ -118,10 +118,14 @@ const filteredGallery = computed(
const expandedGalleryItem = ref(null) const expandedGalleryItem = ref(null)
const expandedGalleryIndex = ref(0) const expandedGalleryIndex = ref(0)
const zoomedIn = ref(false) const zoomedIn = ref(false)
let adsWindowHold = false
const hideImage = () => { const hideImage = () => {
expandedGalleryItem.value = null expandedGalleryItem.value = null
show_ads_window() if (adsWindowHold) {
adsWindowHold = false
release_ads_window_hold()
}
} }
const nextImage = () => { const nextImage = () => {
@@ -149,7 +153,10 @@ const previousImage = () => {
} }
const expandImage = (item, index) => { const expandImage = (item, index) => {
hide_ads_window() if (!adsWindowHold) {
adsWindowHold = true
take_ads_window_hold()
}
expandedGalleryItem.value = item expandedGalleryItem.value = item
expandedGalleryIndex.value = index expandedGalleryIndex.value = index
zoomedIn.value = false zoomedIn.value = false
@@ -181,6 +188,10 @@ onMounted(() => {
onUnmounted(() => { onUnmounted(() => {
document.removeEventListener('keydown', keyListener) document.removeEventListener('keydown', keyListener)
if (adsWindowHold) {
adsWindowHold = false
release_ads_window_hold()
}
}) })
</script> </script>
+1 -1
View File
@@ -318,7 +318,7 @@ fn main() {
.commands(&[ .commands(&[
"init_ads_window", "init_ads_window",
"hide_ads_window", "hide_ads_window",
"show_ads_window", "update_ads_window_hold",
"show_ads_consent_ui", "show_ads_consent_ui",
"expand_ads_consent_webview", "expand_ads_consent_webview",
"open_ads_consent_preferences", "open_ads_consent_preferences",
+97 -141
View File
@@ -3,14 +3,14 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tauri::plugin::TauriPlugin; use tauri::plugin::TauriPlugin;
use tauri::{Emitter, Manager, PhysicalPosition, PhysicalSize, Rect, Runtime}; use tauri::{Emitter, Manager, PhysicalPosition, PhysicalSize, Runtime};
use tauri_plugin_opener::OpenerExt; use tauri_plugin_opener::OpenerExt;
use theseus::settings; use theseus::settings;
use tokio::sync::RwLock; use tokio::sync::RwLock;
pub struct AdsState { pub struct AdsState {
pub shown: bool, pub shown: bool,
pub modal_shown: bool, pub visibility_holds: usize,
pub consent_required: bool, pub consent_required: bool,
pub consent_notification_enabled: bool, pub consent_notification_enabled: bool,
pub consent_overlay_shown: bool, pub consent_overlay_shown: bool,
@@ -24,6 +24,11 @@ const ADS_CONSENT_REQUIRED_EVENT: &str = "ads-consent-required";
const APP_TITLE_BAR_HEIGHT: f32 = 48.0; const APP_TITLE_BAR_HEIGHT: f32 = 48.0;
#[cfg(any(windows, target_os = "macos"))] #[cfg(any(windows, target_os = "macos"))]
pub(super) const OCCLUDED_AREA_THRESHOLD: f64 = 0.5; pub(super) const OCCLUDED_AREA_THRESHOLD: f64 = 0.5;
fn should_show_ads_webview(state: &AdsState) -> bool {
state.shown && (state.visibility_holds == 0 || state.consent_overlay_shown)
}
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
const ADS_USER_AGENT: &str = concat!( const ADS_USER_AGENT: &str = concat!(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ",
@@ -126,28 +131,6 @@ fn set_webview_visible<R: Runtime>(webview: &tauri::Webview<R>, visible: bool) {
} }
} }
fn set_webview_visible_for_window<R: Runtime>(
app: &tauri::AppHandle<R>,
webview: &tauri::Webview<R>,
visible: bool,
) {
let is_minimized = app
.get_window("main")
.and_then(|window| window.is_minimized().ok())
.unwrap_or(false);
let (is_occluded, consent_overlay_shown) = app
.state::<RwLock<AdsState>>()
.try_read()
.map(|state| (state.occluded, state.consent_overlay_shown))
.unwrap_or((false, false));
set_webview_visible(
webview,
visible && !is_minimized && (!is_occluded || consent_overlay_shown),
);
}
#[cfg(any(windows, target_os = "macos"))] #[cfg(any(windows, target_os = "macos"))]
fn compute_ads_webview_occlusion<R: Runtime>( fn compute_ads_webview_occlusion<R: Runtime>(
app: &tauri::AppHandle<R>, app: &tauri::AppHandle<R>,
@@ -203,8 +186,7 @@ async fn sync_ads_occlusion<R: Runtime>(app: &tauri::AppHandle<R>) {
} }
state.occluded = occluded; state.occluded = occluded;
let visible = let visible = should_show_ads_webview(&state);
state.shown && (!state.modal_shown || state.consent_overlay_shown);
drop(state); drop(state);
if let Some(webview) = app.webviews().get("ads-window") { if let Some(webview) = app.webviews().get("ads-window") {
@@ -225,8 +207,7 @@ fn sync_webview_visibility_for_main_window<R: Runtime>(
} else { } else {
match app.state::<RwLock<AdsState>>().try_read() { match app.state::<RwLock<AdsState>>().try_read() {
Ok(state) => Some(( Ok(state) => Some((
state.shown should_show_ads_webview(&state)
&& (!state.modal_shown || state.consent_overlay_shown)
&& (!state.occluded || state.consent_overlay_shown), && (!state.occluded || state.consent_overlay_shown),
state.consent_overlay_shown, state.consent_overlay_shown,
)), )),
@@ -277,7 +258,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.setup(|app, _api| { .setup(|app, _api| {
app.manage(RwLock::new(AdsState { app.manage(RwLock::new(AdsState {
shown: true, shown: true,
modal_shown: false, visibility_holds: 0,
consent_required: false, consent_required: false,
consent_notification_enabled: false, consent_notification_enabled: false,
consent_overlay_shown: false, consent_overlay_shown: false,
@@ -297,7 +278,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.try_read() .try_read()
.map(|state| { .map(|state| {
state.shown state.shown
&& !state.modal_shown && state.visibility_holds == 0
&& !state.consent_required && !state.consent_required
&& !state.consent_overlay_shown && !state.consent_overlay_shown
&& !state.occluded && !state.occluded
@@ -362,7 +343,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
init_ads_window, init_ads_window,
hide_ads_window, hide_ads_window,
show_ads_window, update_ads_window_hold,
show_ads_consent_ui, show_ads_consent_ui,
expand_ads_consent_webview, expand_ads_consent_webview,
open_ads_consent_preferences, open_ads_consent_preferences,
@@ -431,6 +412,46 @@ fn get_device_pixel_ratio<R: Runtime>(
}) })
} }
fn sync_ads_webview_visibility<R: Runtime>(
app: &tauri::AppHandle<R>,
state: &AdsState,
dpr: f32,
) -> crate::api::Result<()> {
let webviews = app.webviews();
let Some(webview) = webviews.get("ads-window") else {
return Ok(());
};
if should_show_ads_webview(state) {
let (position, size) = if state.consent_overlay_shown {
get_overlay_webview_position(app)?
} else {
get_webview_position(app, dpr)?
};
let is_minimized = app
.get_window("main")
.and_then(|window| window.is_minimized().ok())
.unwrap_or(false);
webview.set_size(size).ok();
webview.set_position(position).ok();
webview.show().ok();
set_webview_visible(
webview,
!is_minimized && (!state.occluded || state.consent_overlay_shown),
);
} else {
webview
.set_position(PhysicalPosition::new(-1000, -1000))
.ok();
webview.hide().ok();
set_webview_visible(webview, false);
}
Ok(())
}
#[tauri::command] #[tauri::command]
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
pub async fn init_ads_window<R: Runtime>( pub async fn init_ads_window<R: Runtime>(
@@ -447,10 +468,6 @@ pub async fn init_ads_window<R: Runtime>(
state.shown = true; state.shown = true;
} }
if state.modal_shown && !state.consent_overlay_shown {
return Ok(());
}
let layout = if state.consent_overlay_shown { let layout = if state.consent_overlay_shown {
get_overlay_webview_position(&app) get_overlay_webview_position(&app)
} else { } else {
@@ -459,21 +476,7 @@ pub async fn init_ads_window<R: Runtime>(
if let Ok((position, size)) = layout { if let Ok((position, size)) = layout {
let webview = if let Some(webview) = app.webviews().get("ads-window") { let webview = if let Some(webview) = app.webviews().get("ads-window") {
// set both the `hide`/`show` state and `position`, sync_ads_webview_visibility(&app, &state, dpr)?;
// to ensure that the webview is actually shown/hidden
if state.shown {
webview.show().ok();
webview.set_position(position).ok();
webview.set_size(size).ok();
set_webview_visible_for_window(&app, webview, true);
} else {
webview.hide().ok();
webview
.set_position(PhysicalPosition::new(-1000, -1000))
.ok();
set_webview_visible(webview, false);
}
Some(webview.clone()) Some(webview.clone())
} else if let Some(window) = app.get_window("main") { } else if let Some(window) = app.get_window("main") {
let ads_consent_script = [ let ads_consent_script = [
@@ -510,7 +513,7 @@ pub async fn init_ads_window<R: Runtime>(
}), }),
// set both the `hide`/`show` state and `position`, // set both the `hide`/`show` state and `position`,
// to ensure that the webview is actually shown/hidden // to ensure that the webview is actually shown/hidden
if state.shown { if should_show_ads_webview(&state) {
position position
} else { } else {
PhysicalPosition::new(-1000.0, -1000.0) PhysicalPosition::new(-1000.0, -1000.0)
@@ -518,13 +521,7 @@ pub async fn init_ads_window<R: Runtime>(
size, size,
)?; )?;
if state.shown { sync_ads_webview_visibility(&app, &state, dpr)?;
webview.show().ok();
set_webview_visible_for_window(&app, &webview, true);
} else {
webview.hide().ok();
set_webview_visible(&webview, false);
}
webview.with_webview(#[allow(unused_variables)] |webview2| { webview.with_webview(#[allow(unused_variables)] |webview2| {
#[cfg(windows)] #[cfg(windows)]
@@ -672,38 +669,32 @@ pub async fn init_ads_window<R: Runtime>(
pub async fn init_ads_window() {} pub async fn init_ads_window() {}
#[tauri::command] #[tauri::command]
pub async fn show_ads_window<R: Runtime>( pub async fn update_ads_window_hold<R: Runtime>(
app: tauri::AppHandle<R>, app: tauri::AppHandle<R>,
acquire: bool,
dpr: f32, dpr: f32,
) -> crate::api::Result<()> { ) -> crate::api::Result<()> {
let mut show_consent_notification = false; let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
if let Some(webview) = app.webviews().get("ads-window") { if acquire {
let state = app.state::<RwLock<AdsState>>(); state.visibility_holds = state.visibility_holds.saturating_add(1);
let mut state = state.write().await; } else if state.visibility_holds > 0 {
state.visibility_holds -= 1;
state.modal_shown = false; } else {
tracing::warn!(
if state.shown { "Attempted to release an ads window hold when none were active"
let (position, size) = if state.consent_overlay_shown { );
get_overlay_webview_position(&app)?
} else {
get_webview_position(&app, dpr)?
};
// set both the `hide`/`show` state and `position`,
// to ensure that the webview is actually shown/hidden
webview.set_size(size).ok();
webview.set_position(position).ok();
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
}
show_consent_notification = state.shown
&& state.consent_required
&& state.consent_notification_enabled;
} }
if show_consent_notification { sync_ads_webview_visibility(&app, &state, dpr)?;
if !acquire
&& state.visibility_holds == 0
&& state.shown
&& state.consent_required
&& state.consent_notification_enabled
{
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok(); app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
} }
@@ -722,29 +713,11 @@ pub async fn hide_ads_window<R: Runtime>(
if reset { if reset {
state.shown = false; state.shown = false;
state.consent_overlay_shown = false; state.consent_overlay_shown = false;
} sync_ads_webview_visibility(
&app,
if let Some(webview) = app.webviews().get("ads-window") { &state,
if !reset { get_device_pixel_ratio(&app, None),
state.modal_shown = true; )?;
if state.consent_overlay_shown {
let (position, size) = get_overlay_webview_position(&app)?;
webview.set_size(size).ok();
webview.set_position(position).ok();
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
return Ok(());
}
}
// set both the `hide`/`show` state and `position`,
// to ensure that the webview is actually shown/hidden
webview
.set_position(PhysicalPosition::new(-1000, -1000))
.ok();
webview.hide().ok();
} }
if reset { if reset {
@@ -761,7 +734,7 @@ pub async fn show_ads_consent_ui<R: Runtime>(
) -> crate::api::Result<()> { ) -> crate::api::Result<()> {
let mut show_notification = false; let mut show_notification = false;
if let Some(webview) = app.webviews().get("ads-window") { if app.webviews().contains_key("ads-window") {
let state = app.state::<RwLock<AdsState>>(); let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await; let mut state = state.write().await;
@@ -772,14 +745,11 @@ pub async fn show_ads_consent_ui<R: Runtime>(
state.consent_overlay_shown = false; state.consent_overlay_shown = false;
show_notification = state.shown && notification_enabled; show_notification = state.shown && notification_enabled;
if state.shown && !state.modal_shown { sync_ads_webview_visibility(
let dpr = get_device_pixel_ratio(&app, None); &app,
let (position, size) = get_webview_position(&app, dpr)?; &state,
webview.set_size(size).ok(); get_device_pixel_ratio(&app, None),
webview.set_position(position).ok(); )?;
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
}
} }
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, show_notification) app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, show_notification)
@@ -792,7 +762,7 @@ pub async fn show_ads_consent_ui<R: Runtime>(
pub async fn expand_ads_consent_webview<R: Runtime>( pub async fn expand_ads_consent_webview<R: Runtime>(
app: tauri::AppHandle<R>, app: tauri::AppHandle<R>,
) -> crate::api::Result<()> { ) -> crate::api::Result<()> {
if let Some(webview) = app.webviews().get("ads-window") { if app.webviews().contains_key("ads-window") {
let state = app.state::<RwLock<AdsState>>(); let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await; let mut state = state.write().await;
@@ -801,16 +771,11 @@ pub async fn expand_ads_consent_webview<R: Runtime>(
} }
state.consent_overlay_shown = true; state.consent_overlay_shown = true;
sync_ads_webview_visibility(
let (position, size) = get_overlay_webview_position(&app)?; &app,
webview &state,
.set_bounds(Rect { get_device_pixel_ratio(&app, None),
position: position.into(), )?;
size: size.into(),
})
.ok();
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
} }
Ok(()) Ok(())
@@ -854,20 +819,11 @@ pub async fn finish_ads_consent_flow<R: Runtime>(
state.consent_notification_enabled = false; state.consent_notification_enabled = false;
state.consent_overlay_shown = false; state.consent_overlay_shown = false;
if state.shown && !state.modal_shown { sync_ads_webview_visibility(
let dpr = get_device_pixel_ratio(&app, dpr); &app,
let (position, size) = get_webview_position(&app, dpr)?; &state,
get_device_pixel_ratio(&app, dpr),
webview.set_size(size).ok(); )?;
webview.set_position(position).ok();
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
} else {
webview
.set_position(PhysicalPosition::new(-1000, -1000))
.ok();
webview.hide().ok();
}
drop(state); drop(state);