Skip to content

hide ads properly#3182

Draft
ryanbarlow97 wants to merge 4 commits intomainfrom
hideads
Draft

hide ads properly#3182
ryanbarlow97 wants to merge 4 commits intomainfrom
hideads

Conversation

@ryanbarlow97
Copy link
Contributor

@ryanbarlow97 ryanbarlow97 commented Feb 11, 2026

Description:

Ads were only using tailwind "hidden" but were still being rendered on the left/right:
image

This PR hides ads without rendering the component - which fixes the bug of not being able to close modals by clicking where the ad would have been.

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

w.o.n

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Walkthrough

This change updates GutterAds to set isVisible to false when ad containers are missing or when exceptions occur during ad loading, ensuring the component hides itself on those error paths without changing exported declarations.

Changes

Cohort / File(s) Summary
Gutter ad error-path visibility
src/client/GutterAds.ts
On missing ad container elements or when ad loading throws exceptions, the code now sets isVisible = false. Adjusts control flow to hide the component on ad resource/order failures; no public API or exported declarations changed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🧭 When ads go missing or code meets a scare,
GutterAds quietly hides, out of care.
No frantic errors, no chaotic scene—
A calm little toggle, tidy and clean.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'hide ads properly' directly reflects the main change: hiding ads without rendering the component to fix modal interaction bugs.
Description check ✅ Passed The description clearly explains the bug (ads using only Tailwind 'hidden' still rendered), the solution (hide without rendering), and the impact (fixes modal-closing issue).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/client/GutterAds.ts`:
- Around line 76-89: The close() method leaves this.isVisible true so the
component can reload ads on the next resize; update close() (in GutterAds) to
set this.isVisible = false (or otherwise mark the component as closed) and
ensure any flags that allow handleViewportChange() to call loadAds() are
disabled; specifically modify close() to set this.isVisible = false and stop any
probes so handleViewportChange() will no longer call loadAds() after close().
- Around line 175-194: The interval started in startNoContentCheck() never gets
cleared when ads load successfully; update startNoContentCheck() so that when
noContentCheckCount >= 10 you always call stopNoContentCheck() (move the
stopNoContentCheck() call out of the !this.adLoaded branch), then set
this.isProbingAds = false and this.adLoaded = this.leftAdVisible ||
this.rightAdVisible and, if !this.adLoaded, set this.isVisible = false; ensure
references to stopNoContentCheck(), noContentCheckCount, isProbingAds, and
adLoaded in the startNoContentCheck() function are used accordingly.
🧹 Nitpick comments (2)
src/client/GutterAds.ts (2)

39-53: Missing cleanup for userMeResponse listener

The "userMeResponse" event listener added to document is never removed in disconnectedCallback. If the element is ever removed and re-added, this stacks up duplicate listeners. Store the handler as a class field and remove it on disconnect, similar to what you do with handleViewportChange.

Proposed fix

Add a field for the handler and wire up removal:

+ private handleUserMeResponse = () => {
+   if (window.adsEnabled) {
+     console.log("showing gutter ads");
+     this.show();
+   } else {
+     console.log("not showing gutter ads");
+   }
+ };
+
  connectedCallback() {
    super.connectedCallback();
    this.xlMediaQuery = window.matchMedia("(min-width: 1280px)");
    this.isXlViewport = this.xlMediaQuery.matches;
    this.xlMediaQuery.addEventListener("change", this.handleViewportChange);
-
-   document.addEventListener("userMeResponse", () => {
-     if (window.adsEnabled) {
-       console.log("showing gutter ads");
-       this.show();
-     } else {
-       console.log("not showing gutter ads");
-     }
-   });
+   document.addEventListener("userMeResponse", this.handleUserMeResponse);
  }
  disconnectedCallback() {
    this.xlMediaQuery?.removeEventListener("change", this.handleViewportChange);
    this.xlMediaQuery = null;
    this.stopNoContentCheck();
+   document.removeEventListener("userMeResponse", this.handleUserMeResponse);
    super.disconnectedCallback();
  }

215-224: Duplicated visible-class string — extract to a shared constant

leftClass and rightClass use the same long class string when the ad is visible. Pull it into a local constant to keep things tidy and avoid drift.

Proposed refactor
+   const visibleClass =
+     "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center";
    const probeClass =
      "absolute w-px h-px overflow-hidden pointer-events-none opacity-0";
-   const leftClass = this.leftAdVisible
-     ? "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center"
-     : probeClass;
-   const rightClass = this.rightAdVisible
-     ? "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center"
-     : probeClass;
+   const leftClass = this.leftAdVisible ? visibleClass : probeClass;
+   const rightClass = this.rightAdVisible ? visibleClass : probeClass;

@github-project-automation github-project-automation bot moved this from Triage to Development in OpenFront Release Management Feb 11, 2026
@ryanbarlow97 ryanbarlow97 added UI/UX UI/UX changes including assets, menus, QoL, etc. Bugfix Fixes a bug labels Feb 11, 2026
@ryanbarlow97 ryanbarlow97 added this to the v30 milestone Feb 11, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/client/GutterAds.ts (1)

39-53: ⚠️ Potential issue | 🟡 Minor

Event listener for "userMeResponse" is never removed

The "userMeResponse" listener is added in connectedCallback but not cleaned up in disconnectedCallback. If this element is ever removed and re-added, a new listener stacks on top of the old one.

Store the handler as a class field and remove it on disconnect, same as you do for handleViewportChange.

Proposed fix
+ private handleUserMeResponse = () => {
+   if (window.adsEnabled) {
+     console.log("showing gutter ads");
+     this.show();
+   } else {
+     console.log("not showing gutter ads");
+   }
+ };
+
  connectedCallback() {
    super.connectedCallback();
    this.xlMediaQuery = window.matchMedia("(min-width: 1280px)");
    this.isXlViewport = this.xlMediaQuery.matches;
    this.xlMediaQuery.addEventListener("change", this.handleViewportChange);

-   document.addEventListener("userMeResponse", () => {
-     if (window.adsEnabled) {
-       console.log("showing gutter ads");
-       this.show();
-     } else {
-       console.log("not showing gutter ads");
-     }
-   });
+   document.addEventListener("userMeResponse", this.handleUserMeResponse);
  }
  disconnectedCallback() {
    this.xlMediaQuery?.removeEventListener("change", this.handleViewportChange);
    this.xlMediaQuery = null;
    this.stopNoContentCheck();
+   document.removeEventListener("userMeResponse", this.handleUserMeResponse);
    super.disconnectedCallback();
  }
🤖 Fix all issues with AI agents
In `@src/client/GutterAds.ts`:
- Around line 93-107: The viewport-change handler (handleViewportChange)
currently only calls close() when !isXlViewport && adLoaded, which lets a
pending probe (isProbingAds true) complete and start the no-content timer
against removed containers; update the guard to also close when a probe is
active (e.g., if (!this.isXlViewport && (this.adLoaded || this.isProbingAds))
this.close()), and ensure close() also clears any probing/no-content timers or
cancels pending ramp.que callbacks so no timers run after the container has been
removed.
🧹 Nitpick comments (2)
src/client/GutterAds.ts (2)

130-157: adLoaded is used for two different things

At line 143, adLoaded is set to true as a guard against double-loading. Then at line 190, probing may override it to false. Meanwhile, handleViewportChange (line 96) reads it as "ads are confirmed loaded."

Consider splitting this into two flags — one for "load requested" (guard) and one for "content confirmed" — so the meaning is clear and you avoid relying on the override.


219-226: Visible class string is duplicated for left and right

leftClass and rightClass share the exact same visible-state string. Extract it once to keep things tidy.

Proposed fix
    const probeClass =
      "absolute w-px h-px overflow-hidden pointer-events-none opacity-0";
+   const visibleClass =
+     "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center";
-   const leftClass = this.leftAdVisible
-     ? "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center"
-     : probeClass;
-   const rightClass = this.rightAdVisible
-     ? "fixed flex transform -translate-y-1/2 w-[160px] min-h-[600px] z-[100] pointer-events-auto items-center justify-center"
-     : probeClass;
+   const leftClass = this.leftAdVisible ? visibleClass : probeClass;
+   const rightClass = this.rightAdVisible ? visibleClass : probeClass;

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/client/GutterAds.ts`:
- Around line 64-80: show() currently resets state and starts a new load cycle
but doesn't tear down existing ramp units, causing duplicate/orphaned units;
modify show() to call the existing close() (or invoke window.ramp.destroyUnits
when available) at the top whenever adLoaded or adLoadRequested is true so any
previously created units are destroyed before resetting state, then proceed with
incrementing adWorkToken, resetting flags (adLoaded, adLoadRequested,
leftAdVisible, rightAdVisible, isProbingAds) and requesting an update; ensure
you reference the show() and close() methods and the window.ramp.destroyUnits
path so the old units are reliably cleaned up before loadAds() is scheduled.
- Around line 228-235: disconnectedCallback currently increments adWorkToken,
removes listeners, nulls xlMediaQuery and stops timers but doesn't destroy Ramp
ad units; update disconnectedCallback to call this.close() (which already wraps
ramp.destroyUnits calls) so Ramp can clean up its unit references when the
element is removed, keeping the existing adWorkToken increment, xlMediaQuery
removal, handleViewportChange/handleUserMeResponse listener removals and
stopNoContentCheck call intact.
🧹 Nitpick comments (1)
src/client/GutterAds.ts (1)

208-216: adLoadRequested = false on line 214 is redundant

Line 212 already sets adLoadRequested = this.adLoaded. When adLoaded is false, adLoadRequested is already false by the time line 214 runs. You can drop line 214 for clarity.

Proposed fix
      if (this.noContentCheckCount >= 10) {
        this.stopNoContentCheck();
        this.isProbingAds = false;
        this.adLoaded = this.leftAdVisible || this.rightAdVisible;
        this.adLoadRequested = this.adLoaded;
        if (!this.adLoaded) {
-         this.adLoadRequested = false;
          this.isVisible = false;
        }
      }

Copy link
Collaborator

@evanpelle evanpelle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't there a simpler way? just like:

ifNoAdd { return html``}

is what i'm imagining

@ryanbarlow97 ryanbarlow97 marked this pull request as draft February 12, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bugfix Fixes a bug UI/UX UI/UX changes including assets, menus, QoL, etc.

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

2 participants

Comments