Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Publisher Button + Examples
  • Loading branch information
Cameron Neale
Cameron Neale committed Aug 3, 2026
commit d6a1ce9818c43aa6960e9a96e98cfadfac3bca73
61 changes: 53 additions & 8 deletions examples/test-publisher-button.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,53 @@
font-family: Arial, sans-serif;
margin: 40px;
line-height: 1.6;
background-color: #f9f9f9;
color: #333;
background-color: #121212;
color: #e3e3e3;
}
.container {
max-width: 800px;
margin: 0 auto;
background: #ffffff;
background: #1e1e1e;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
box-shadow: 0 2px 10px rgba(0,0,0,0.5);
}
h1 {
color: #1a73e8;
color: #8ab4f8;
}
h3 {
color: #e8eaed;
}
code {
background: #2d2d2d;
padding: 2px 6px;
border-radius: 4px;
color: #a8c7fa;
}
.card {
border: 1px solid #dadce0;
border: 1px solid #3c4043;
border-radius: 8px;
padding: 20px;
margin-top: 20px;
background: #fafafa;
background: #242526;
}
.button-wrapper {
margin-top: 15px;
}
.custom-button {
background-color: #8ab4f8;
color: #121212;
border: none;
padding: 12px 24px;
font-size: 14px;
font-weight: bold;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.2s;
}
.custom-button:hover {
background-color: #a8c7fa;
}
</style>

<!--
Expand Down Expand Up @@ -64,12 +87,34 @@ <h3>Add Preferred Source Button Embed #2 (Footer / Multi-Inflation Test)</h3>
<div google-add-preferred-source-btn></div>
</div>
</div>

<div class="card">
<h3>Add Preferred Source Embed #3 (Custom Bespoke Button via API)</h3>
<p>This button is a bespoke publisher-styled button that calls <code>api.addPreferredSource()</code> manually when clicked:</p>

<div class="button-wrapper">
<button id="custom-add-btn" class="custom-button">Custom Add Preferred Source Button</button>
</div>
</div>
</div>

<script>
// Optional programmatic listener / initialization hook
// Initialize PublisherRuntime with dark theme and English language ('en')
(self.PREFERRED_SOURCE = self.PREFERRED_SOURCE || []).push((api) => {
api.init({
theme: 'dark',
lang: 'en',
});
console.log('PublisherRuntime initialized with API:', api);

document.getElementById('custom-add-btn').addEventListener('click', () => {
console.log('Custom button clicked! Triggering api.addPreferredSource()...');
api.addPreferredSource().then((status) => {
console.log('addPreferredSource flow completed with status:', status);
}).catch((err) => {
console.error('addPreferredSource flow failed or cancelled:', err);
});
});
});
</script>
</body>
Expand Down
31 changes: 31 additions & 0 deletions src/runtime/add-preferred-source-flow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,35 @@ describes.realWin('AddPreferredSourceFlow', (env) => {
onResultCallback(port);
await startPromise;
});

it('passes window location href in source URL query param', async () => {
let onResultCallback;
activitiesMock
.expects('onResult')
.withExactArgs(
'addPreferredSource',
sandbox.match((arg) => {
onResultCallback = arg;
return typeof arg == 'function';
})
)
.once();
activitiesMock
.expects('open')
.withExactArgs(
'addPreferredSource',
sandbox.match(
(url) =>
url.includes('/addpreferredsource') && url.includes('source=')
),
'_blank',
sandbox.match.object,
sandbox.match.object
)
.once();

const startPromise = flow.start();
onResultCallback(port);
await startPromise;
});
});
1 change: 1 addition & 0 deletions src/runtime/add-preferred-source-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class AddPreferredSourceFlow {

const queryParams: {[key: string]: string} = {
hl: this.deps_.clientConfigManager().getLanguage(),
source: this.win_.location.href,
};
this.activityPorts_.open(
ADD_PREFERRED_SOURCE_REQUEST_ID,
Expand Down
32 changes: 21 additions & 11 deletions src/runtime/publisher-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,32 @@ export class PublisherRuntime {
buttonComponent.updateStatus(this.currentStatus_);
}
buttonComponent.attach(() => {
this.updateAllButtons(
AddPreferredSourceStatus.ADD_PREFERRED_SOURCE_STATUS_SUCCESS
);
this.addPreferredSource();
return Promise.resolve(true);
});
}
}

showToast(status: AddPreferredSourceStatus, sourceName = ''): void {
const runtime = this.getRuntime_();
const params: {[key: string]: string} = {
flavor: 'preferred_source',
sourceName,
confirmationType: `${status}`,
hl: runtime.clientConfigManager().getLanguage(),
};
if (this.options_.theme) {
params['theme'] = this.options_.theme;
}
const toast = new Toast(
runtime,
feUrl('/toastiframe', params),
{},
'publisher-toast'
);
toast.open();
}

addPreferredSource(): void {
const runtime = this.getRuntime_();
const flow = new AddPreferredSourceFlow(runtime);
Expand All @@ -116,14 +133,7 @@ export class PublisherRuntime {
AddPreferredSourceStatus.ADD_PREFERRED_SOURCE_STATUS_INELIGIBLE
) {
this.updateAllButtons(status);
const params: {[key: string]: string} = {
flavor: 'preferred_source',
sourceName: response.getSiteName() || '',
confirmationType: `${status}`,
hl: runtime.clientConfigManager().getLanguage(),
};
const toast = new Toast(runtime, feUrl('/toastiframe', params));
toast.open();
this.showToast(status, response.getSiteName() || '');
}
})
.catch(() => {
Expand Down
12 changes: 7 additions & 5 deletions src/ui/add-preferred-source-button-iframe-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ describes.realWin('AddPreferredSourceButtonIframe', (env) => {
doc = env.win.document;

portStub = sandbox.createStubInstance(ActivityIframePort);
portStub.onResizeRequest.callsFake((cb) => {
// simulate resize
cb(200);
});
portStub.whenReady.resolves();
portStub.acceptResult.resolves(true);
portStub.on.callsFake((ctor, cb) => {
Expand Down Expand Up @@ -70,9 +66,15 @@ describes.realWin('AddPreferredSourceButtonIframe', (env) => {
resultCalled = true;
});

expect(container.style.position).to.equal('relative');
expect(container.style.width).to.equal('100%');
expect(container.style.minHeight).to.equal('60px');

const iframe = container.querySelector('iframe');
expect(iframe).to.not.be.null;
expect(iframe.style.height).to.equal('200px'); // Resized
expect(iframe.style.position).to.equal('absolute');
expect(iframe.style.height).to.equal('100%');
expect(iframe.style.width).to.equal('100%');
expect(iframe.getAttribute('frameborder')).to.equal('0');
expect(iframe.getAttribute('scrolling')).to.equal('no');

Expand Down
43 changes: 27 additions & 16 deletions src/ui/add-preferred-source-button-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Deps} from '../runtime/deps';
import {feUrl} from '../runtime/services';
import {log} from '../utils/log';
import {parseUrl} from '../utils/url';
import {setStyle, setStyles} from '../utils/style';
import {setStyles} from '../utils/style';

export class AddPreferredSourceButtonIframe {
private readonly activityPorts_: ActivityPorts;
Expand All @@ -25,24 +25,32 @@ export class AddPreferredSourceButtonIframe {
async updateStatus(status: AddPreferredSourceStatus): Promise<void> {
if (this.portPromise_) {
try {
log(`[AddPreferredSourceButtonIframe] Awaiting portPromise_ for status ${status}`);
log(
`[AddPreferredSourceButtonIframe] Awaiting portPromise_ for status ${status}`
);
const port = await this.portPromise_;
const updateMsg = new UpdateAddPreferredSourceButtonRequest();
updateMsg.setStatus(status);
log(
'[AddPreferredSourceButtonIframe] Updating iframe button status:',
status, 'on port', port
status,
'on port',
port
);
port.execute(updateMsg);
log(`[AddPreferredSourceButtonIframe] Successfully executed updateMsg on port for status ${status}`);
log(
`[AddPreferredSourceButtonIframe] Successfully executed updateMsg on port for status ${status}`
);
} catch (reason) {
log(
'[AddPreferredSourceButtonIframe] Error updating status on port:',
reason
);
}
} else {
log(`[AddPreferredSourceButtonIframe] No portPromise_ available for status ${status}`);
log(
`[AddPreferredSourceButtonIframe] No portPromise_ available for status ${status}`
);
}
}

Expand All @@ -54,10 +62,22 @@ export class AddPreferredSourceButtonIframe {
iframe.setAttribute('scrolling', 'no');
iframe.setAttribute('title', 'Add Preferred Source');

// Default styling so that it's invisible until loaded, or handles sizing.
// The iframe contents should tell us its size.
// Style container and iframe with absolute positioning matching swg-smart-button.
// Setting width 100% and min-height 60px ensures safe vertical clearance.
setStyles(this.container_ as HTMLElement, {
'position': 'relative',
'width': '100%',
'min-height': '60px',
});
setStyles(iframe, {
'opacity': '1',
'position': 'absolute',
'top': '0',
'bottom': '0',
'left': '0',
'right': '0',
'width': '100%',
'height': '100%',
'border': 'none',
});

Expand Down Expand Up @@ -85,15 +105,6 @@ export class AddPreferredSourceButtonIframe {
'[AddPreferredSourceButtonIframe] ActivityPort connected successfully.'
);

port.onResizeRequest((height) => {
log(
'[AddPreferredSourceButtonIframe] Resize request received:',
height
);
setStyle(iframe, 'height', `${height}px`);
port.resized();
});

log(
'[AddPreferredSourceButtonIframe] Registering listener for AddPreferredSourceRequest clicks...'
);
Expand Down
15 changes: 12 additions & 3 deletions src/ui/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export class Toast {
constructor(
deps: Deps,
private readonly src_: string,
private readonly args_: {[key: string]: string} = {}
private readonly args_: {[key: string]: string} = {},
private readonly className_: string = 'swg-toast'
) {
this.doc_ = deps.doc();

Expand All @@ -56,7 +57,7 @@ export class Toast {
const iframeAttributes = {
'frameborder': '0',
'scrolling': 'no',
'class': 'swg-toast',
'class': this.className_,
'title': title,
};

Expand Down Expand Up @@ -94,8 +95,16 @@ export class Toast {
this.src_,
this.args_
);
let hasResized = false;
port.onResizeRequest((height) => {
hasResized = true;
setImportantStyles(this.iframe_, {'height': `${height}px`});
port.resized();
});
await port.whenReady();
resetStyles(this.iframe_, ['height']);
if (!hasResized) {
resetStyles(this.iframe_, ['height']);
}

this.animating_ = this.animate_({
callback: () => {
Expand Down
Loading