mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 09:04:55 +00:00
fix: hide ad webview when showing fullscreen content (#7110)
* fix: hide ad webview when showing fullscreen content * fixes
This commit is contained in:
@@ -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()))
|
||||||
|
|||||||
+1
-8
@@ -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()
|
||||||
|
|||||||
-3
@@ -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())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user