mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 09:04:55 +00:00
fix: handling failures/invalid popup edge cases to show normal gdpr popup fallback (#6857)
* fix: remove drilling actions down iframes * refactor: split up custom popup logic, trim it down a lot * fix: bring back TCF useractioncomplete and USP/GPP sectionChange event listeners, and only using dom observer as the fallback * remove open devtools * format * harden CPM fallbacks for unknown layouts * consolidate timeouts * refactor: rename functions to make sense * fix: sidebar closed on launch does not properly set state
This commit is contained in:
+58
-65
@@ -12,6 +12,7 @@ pub struct AdsState {
|
||||
pub shown: bool,
|
||||
pub modal_shown: bool,
|
||||
pub consent_required: bool,
|
||||
pub consent_notification_enabled: bool,
|
||||
pub consent_overlay_shown: bool,
|
||||
pub occluded: bool,
|
||||
pub last_click: Option<Instant>,
|
||||
@@ -278,6 +279,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
shown: true,
|
||||
modal_shown: false,
|
||||
consent_required: false,
|
||||
consent_notification_enabled: false,
|
||||
consent_overlay_shown: false,
|
||||
occluded: false,
|
||||
last_click: None,
|
||||
@@ -361,12 +363,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
init_ads_window,
|
||||
hide_ads_window,
|
||||
show_ads_window,
|
||||
show_ads_consent_overlay,
|
||||
show_ads_consent_preferences,
|
||||
show_ads_consent_ui,
|
||||
expand_ads_consent_webview,
|
||||
open_ads_consent_preferences,
|
||||
hide_ads_consent_preferences,
|
||||
hide_ads_consent_overlay,
|
||||
get_ads_consent_required,
|
||||
finish_ads_consent_flow,
|
||||
should_show_ads_consent_popup,
|
||||
perform_ads_consent_action,
|
||||
record_ads_click,
|
||||
open_link,
|
||||
@@ -475,6 +476,19 @@ pub async fn init_ads_window<R: Runtime>(
|
||||
|
||||
Some(webview.clone())
|
||||
} else if let Some(window) = app.get_window("main") {
|
||||
let ads_consent_script = [
|
||||
"(() => {",
|
||||
include_str!("ads-consent/state.js"),
|
||||
include_str!("ads-consent/styles.js"),
|
||||
include_str!("ads-consent/bridge.js"),
|
||||
include_str!("ads-consent/cmp.js"),
|
||||
include_str!("ads-consent/media.js"),
|
||||
include_str!("ads-consent/controller.js"),
|
||||
include_str!("ads-consent/index.js"),
|
||||
"})()",
|
||||
]
|
||||
.join("\n");
|
||||
|
||||
#[cfg(windows)]
|
||||
let webview_url =
|
||||
WebviewUrl::External("about:blank".parse().unwrap());
|
||||
@@ -483,9 +497,7 @@ pub async fn init_ads_window<R: Runtime>(
|
||||
|
||||
let webview = window.add_child(
|
||||
tauri::webview::WebviewBuilder::new("ads-window", webview_url)
|
||||
.initialization_script_for_all_frames(include_str!(
|
||||
"ads-init.js"
|
||||
))
|
||||
.initialization_script_for_all_frames(ads_consent_script)
|
||||
// We use a standard Chrome user agent for compatibility with our ad provider,
|
||||
// since Tauri is not recognized by ad providers by default.
|
||||
// Aditude has separately informed SSPs and IVT vendors that this traffic
|
||||
@@ -644,7 +656,10 @@ pub async fn init_ads_window<R: Runtime>(
|
||||
// });
|
||||
}
|
||||
|
||||
if state.shown && state.consent_required {
|
||||
if state.shown
|
||||
&& state.consent_required
|
||||
&& state.consent_notification_enabled
|
||||
{
|
||||
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
|
||||
}
|
||||
|
||||
@@ -661,7 +676,7 @@ pub async fn show_ads_window<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
dpr: f32,
|
||||
) -> crate::api::Result<()> {
|
||||
let mut consent_required = false;
|
||||
let mut show_consent_notification = false;
|
||||
|
||||
if let Some(webview) = app.webviews().get("ads-window") {
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
@@ -683,10 +698,12 @@ pub async fn show_ads_window<R: Runtime>(
|
||||
set_webview_visible_for_window(&app, webview, true);
|
||||
}
|
||||
|
||||
consent_required = state.shown && state.consent_required;
|
||||
show_consent_notification = state.shown
|
||||
&& state.consent_required
|
||||
&& state.consent_notification_enabled;
|
||||
}
|
||||
|
||||
if consent_required {
|
||||
if show_consent_notification {
|
||||
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
|
||||
}
|
||||
|
||||
@@ -738,22 +755,24 @@ pub async fn hide_ads_window<R: Runtime>(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn show_ads_consent_overlay<R: Runtime>(
|
||||
pub async fn show_ads_consent_ui<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
notification_enabled: bool,
|
||||
) -> crate::api::Result<()> {
|
||||
let mut show_notification = false;
|
||||
|
||||
if let Some(webview) = app.webviews().get("ads-window") {
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
let mut state = state.write().await;
|
||||
|
||||
// dont show for hidden ads so consent events cannot re-enable the webview.
|
||||
if !state.shown {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Preserve pending consent while the sidebar is hidden, but keep all visibility
|
||||
// changes gated by `state.shown` so consent events cannot re-enable hidden ads.
|
||||
state.consent_required = true;
|
||||
state.consent_notification_enabled = notification_enabled;
|
||||
state.consent_overlay_shown = false;
|
||||
show_notification = state.shown && notification_enabled;
|
||||
|
||||
if !state.modal_shown {
|
||||
if state.shown && !state.modal_shown {
|
||||
let dpr = get_device_pixel_ratio(&app, None);
|
||||
let (position, size) = get_webview_position(&app, dpr)?;
|
||||
webview.set_size(size).ok();
|
||||
@@ -763,13 +782,14 @@ pub async fn show_ads_consent_overlay<R: Runtime>(
|
||||
}
|
||||
}
|
||||
|
||||
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
|
||||
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, show_notification)
|
||||
.ok();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn show_ads_consent_preferences<R: Runtime>(
|
||||
pub async fn expand_ads_consent_webview<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
) -> crate::api::Result<()> {
|
||||
if let Some(webview) = app.webviews().get("ads-window") {
|
||||
@@ -807,53 +827,21 @@ pub async fn open_ads_consent_preferences<R: Runtime>(
|
||||
{
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
let mut state = state.write().await;
|
||||
|
||||
if !state.consent_required {
|
||||
state.consent_notification_enabled = false;
|
||||
}
|
||||
state.consent_required = true;
|
||||
state.consent_overlay_shown = false;
|
||||
}
|
||||
|
||||
webview.eval("window.modrinthAdsReopenConsentPreferences?.()")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Restores the ad inventory bounds without resolving the pending consent request.
|
||||
#[tauri::command]
|
||||
pub async fn hide_ads_consent_preferences<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
) -> crate::api::Result<()> {
|
||||
if let Some(webview) = app.webviews().get("ads-window") {
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
let mut state = state.write().await;
|
||||
|
||||
state.consent_overlay_shown = false;
|
||||
|
||||
if state.shown && !state.modal_shown {
|
||||
let dpr = get_device_pixel_ratio(&app, None);
|
||||
let (position, size) = get_webview_position(&app, dpr)?;
|
||||
|
||||
webview
|
||||
.set_bounds(Rect {
|
||||
position: position.into(),
|
||||
size: size.into(),
|
||||
})
|
||||
.ok();
|
||||
webview.show().ok();
|
||||
set_webview_visible_for_window(&app, webview, true);
|
||||
} else {
|
||||
webview
|
||||
.set_position(PhysicalPosition::new(-1000, -1000))
|
||||
.ok();
|
||||
webview.hide().ok();
|
||||
}
|
||||
}
|
||||
|
||||
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
|
||||
webview.eval("window.modrinthPrivacy?.adsReopenConsentPreferences?.()")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn hide_ads_consent_overlay<R: Runtime>(
|
||||
pub async fn finish_ads_consent_flow<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
dpr: Option<f32>,
|
||||
) -> crate::api::Result<()> {
|
||||
@@ -863,6 +851,7 @@ pub async fn hide_ads_consent_overlay<R: Runtime>(
|
||||
let should_reload_ads = state.consent_required;
|
||||
|
||||
state.consent_required = false;
|
||||
state.consent_notification_enabled = false;
|
||||
state.consent_overlay_shown = false;
|
||||
|
||||
if state.shown && !state.modal_shown {
|
||||
@@ -893,13 +882,15 @@ pub async fn hide_ads_consent_overlay<R: Runtime>(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_ads_consent_required<R: Runtime>(
|
||||
pub async fn should_show_ads_consent_popup<R: Runtime>(
|
||||
app: tauri::AppHandle<R>,
|
||||
) -> crate::api::Result<bool> {
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
let state = state.read().await;
|
||||
|
||||
Ok(state.shown && state.consent_required)
|
||||
Ok(state.shown
|
||||
&& state.consent_required
|
||||
&& state.consent_notification_enabled)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -908,16 +899,18 @@ pub async fn perform_ads_consent_action<R: Runtime>(
|
||||
action: String,
|
||||
) -> crate::api::Result<()> {
|
||||
let script = match action.as_str() {
|
||||
"accept" => "window.modrinthAdsConsentAction?.('accept')",
|
||||
"reject" => "window.modrinthAdsConsentAction?.('reject')",
|
||||
"manage" => "window.modrinthAdsConsentAction?.('manage')",
|
||||
"accept" => "window.modrinthPrivacy?.adsConsentAction?.('accept')",
|
||||
"reject" => "window.modrinthPrivacy?.adsConsentAction?.('reject')",
|
||||
"manage" => "window.modrinthPrivacy?.adsConsentAction?.('manage')",
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
let state = app.state::<RwLock<AdsState>>();
|
||||
let should_perform = {
|
||||
let state = state.read().await;
|
||||
state.shown && state.consent_required
|
||||
state.shown
|
||||
&& state.consent_required
|
||||
&& state.consent_notification_enabled
|
||||
};
|
||||
|
||||
if !should_perform {
|
||||
|
||||
Reference in New Issue
Block a user