Refactor ad implementation, fix two bugs (#616)

This commit is contained in:
Anthony 2022-01-05 16:13:39 +08:00 committed by infinite-persistence
commit ec5a9802fc
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
5 changed files with 141 additions and 381 deletions

View file

@ -84,139 +84,6 @@ function ChannelContent(props: Props) {
setSearchQuery(value); setSearchQuery(value);
} }
// returns true if passed element is fully visible on screen
// function isScrolledIntoView(el) {
// const rect = el.getBoundingClientRect();
// const elemTop = rect.top;
// const elemBottom = rect.bottom;
//
// // Only completely visible elements return true:
// const isVisible = elemTop >= 0 && elemBottom <= window.innerHeight;
// return isVisible;
// }
//
// React.useEffect(() => {
// if (isAuthenticated || !SHOW_ADS) {
// return;
// }
//
// const urlParams = new URLSearchParams(window.location.search);
// const viewType = urlParams.get('view');
//
// // only insert ad if it's a content view
// if (viewType !== 'content') return;
//
// (async function () {
// // test if adblock is enabled
// let adBlockEnabled = false;
// const googleAdUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
// try {
// await fetch(new Request(googleAdUrl)).catch((_) => {
// adBlockEnabled = true;
// });
// } catch (e) {
// adBlockEnabled = true;
// } finally {
// if (!adBlockEnabled) {
// // select the cards on page
// let cards = document.getElementsByClassName('card claim-preview--tile');
//
// // eslint-disable-next-line no-inner-declarations
// function checkFlag() {
// if (cards.length === 0) {
// window.setTimeout(checkFlag, 100);
// } else {
// // find the last fully visible card
// let lastCard;
//
// // width of browser window
// const windowWidth = window.innerWidth;
//
// // on small screens, grab the second item
// if (windowWidth <= 900) {
// lastCard = cards[1];
// } else {
// // otherwise, get the last fully visible card
// for (const card of cards) {
// const isFullyVisible = isScrolledIntoView(card);
// if (!isFullyVisible) break;
// lastCard = card;
// }
// }
//
// // clone the last card
// // $FlowFixMe
// const clonedCard = lastCard.cloneNode(true);
//
// // insert cloned card
// // $FlowFixMe
// lastCard.parentNode.insertBefore(clonedCard, lastCard);
//
// // delete last card so that it doesn't mess up formatting
// // $FlowFixMe
// // lastCard.remove();
//
// // change the appearance of the cloned card
// // $FlowFixMe
// clonedCard.querySelector('.claim__menu-button').remove();
//
// // $FlowFixMe
// clonedCard.querySelector('.truncated-text').innerHTML = __(
// 'Hate these? Login to Odysee for an ad free experience'
// );
//
// // $FlowFixMe
// clonedCard.querySelector('.claim-tile__info').remove();
//
// // $FlowFixMe
// clonedCard.querySelector('[role="none"]').removeAttribute('href');
//
// // $FlowFixMe
// clonedCard.querySelector('.claim-tile__header').firstChild.href = '/$/signin';
//
// // $FlowFixMe
// clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('aria-label');
//
// // $FlowFixMe
// clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('title');
//
// // $FlowFixMe
// clonedCard.querySelector('.claim-tile__header').firstChild.removeAttribute('aria-label');
//
// // $FlowFixMe
// clonedCard
// .querySelector('.media__thumb')
// .replaceWith(document.getElementsByClassName('homepageAdContainer')[0]);
//
// // show the homepage ad which is not displayed at first
// document.getElementsByClassName('homepageAdContainer')[0].style.display = 'block';
//
// // $FlowFixMe
// const imageHeight = window.getComputedStyle(lastCard.querySelector('.media__thumb')).height;
// // $FlowFixMe
// const imageWidth = window.getComputedStyle(lastCard.querySelector('.media__thumb')).width;
//
// const styles = `#av-container, #AVcontent, #aniBox {
// height: ${imageHeight} !important;
// width: ${imageWidth} !important;
// }`;
//
// const styleSheet = document.createElement('style');
// styleSheet.type = 'text/css';
// styleSheet.id = 'customAniviewStyling';
// styleSheet.innerText = styles;
// // $FlowFixMe
// document.head.appendChild(styleSheet);
//
// window.dispatchEvent(new CustomEvent('scroll'));
// }
// }
// checkFlag();
// }
// }
// })();
// }, []);
React.useEffect(() => { React.useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
if (searchQuery === '' || !claimId) { if (searchQuery === '' || !claimId) {
@ -307,7 +174,7 @@ function ChannelContent(props: Props) {
{!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />} {!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />}
<Ads type="homepage" /> {/* <Ads type="homepage" /> */}
{!fetching && ( {!fetching && (
<ClaimListDiscover <ClaimListDiscover

View file

@ -13,7 +13,7 @@ import usePersistedState from 'effects/use-persisted-state';
import analytics from 'analytics'; import analytics from 'analytics';
import HiddenNsfw from 'component/common/hidden-nsfw'; import HiddenNsfw from 'component/common/hidden-nsfw';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import Ads from 'web/component/ads'; import Ads, { injectAd } from 'web/component/ads';
import LbcSymbol from 'component/common/lbc-symbol'; import LbcSymbol from 'component/common/lbc-symbol';
import I18nMessage from 'component/i18nMessage'; import I18nMessage from 'component/i18nMessage';
import moment from 'moment'; import moment from 'moment';
@ -182,131 +182,13 @@ function DiscoverPage(props: Props) {
); );
} }
// returns true if passed element is fully visible on screen
function isScrolledIntoView(el) {
const rect = el.getBoundingClientRect();
const elemTop = rect.top;
const elemBottom = rect.bottom;
// Only completely visible elements return true:
const isVisible = elemTop >= 0 && elemBottom <= window.innerHeight;
return isVisible;
}
React.useEffect(() => { React.useEffect(() => {
if (isAuthenticated || !SHOW_ADS || window.location.pathname === `/$/${PAGES.WILD_WEST}`) { if (isAuthenticated || !SHOW_ADS || window.location.pathname === `/$/${PAGES.WILD_WEST}`) {
return; return;
} }
(async function () { // inject ad into last visible card
// test if adblock is enabled injectAd();
let adBlockEnabled = false;
const googleAdUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
try {
await fetch(new Request(googleAdUrl)).catch((_) => {
adBlockEnabled = true;
});
} catch (e) {
adBlockEnabled = true;
} finally {
if (!adBlockEnabled) {
// select the cards on page
let cards = document.getElementsByClassName('card claim-preview--tile');
// eslint-disable-next-line no-inner-declarations
function checkFlag() {
if (cards.length === 0) {
window.setTimeout(checkFlag, 100);
} else {
// find the last fully visible card
let lastCard;
// width of browser window
const windowWidth = window.innerWidth;
// on small screens, grab the second item
if (windowWidth <= 900) {
lastCard = cards[1];
} else {
// otherwise, get the last fully visible card
for (const card of cards) {
const isFullyVisible = isScrolledIntoView(card);
if (!isFullyVisible) break;
lastCard = card;
}
}
// clone the last card
// $FlowFixMe
const clonedCard = lastCard.cloneNode(true);
// insert cloned card
// $FlowFixMe
lastCard.parentNode.insertBefore(clonedCard, lastCard);
// delete last card so that it doesn't mess up formatting
// $FlowFixMe
// lastCard.remove();
// change the appearance of the cloned card
// $FlowFixMe
clonedCard.querySelector('.claim__menu-button').remove();
// $FlowFixMe
clonedCard.querySelector('.truncated-text').innerHTML = __(
'Hate these? Login to Odysee for an ad free experience'
);
// $FlowFixMe
clonedCard.querySelector('.claim-tile__info').remove();
// $FlowFixMe
clonedCard.querySelector('[role="none"]').removeAttribute('href');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.href = '/$/signin';
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('title');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard
.querySelector('.media__thumb')
.replaceWith(document.getElementsByClassName('homepageAdContainer')[0]);
// show the homepage ad which is not displayed at first
document.getElementsByClassName('homepageAdContainer')[0].style.display = 'block';
// $FlowFixMe
const imageHeight = window.getComputedStyle(lastCard.querySelector('.media__thumb')).height;
// $FlowFixMe
const imageWidth = window.getComputedStyle(lastCard.querySelector('.media__thumb')).width;
const styles = `#av-container, #AVcontent, #aniBox {
height: ${imageHeight} !important;
width: ${imageWidth} !important;
}`;
const styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.id = 'customAniviewStyling';
styleSheet.innerText = styles;
// $FlowFixMe
document.head.appendChild(styleSheet);
window.dispatchEvent(new CustomEvent('scroll'));
}
}
checkFlag();
}
}
})();
}, [isAuthenticated]); }, [isAuthenticated]);
// Sync liveSection --> liveSectionStore // Sync liveSection --> liveSectionStore

View file

@ -1,8 +1,8 @@
// @flow // @flow
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import { SHOW_ADS, SITE_NAME, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config'; import { SITE_NAME, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS, SHOW_ADS } from 'config';
import Ads from 'web/component/ads'; import Ads, { injectAd } from 'web/component/ads';
import React from 'react'; import React from 'react';
import Page from 'component/page'; import Page from 'component/page';
import Button from 'component/button'; import Button from 'component/button';
@ -120,128 +120,10 @@ function HomePage(props: Props) {
doFetchActiveLivestreams(); doFetchActiveLivestreams();
}, []); }, []);
// returns true if passed element is fully visible on screen
function isScrolledIntoView(el) {
const rect = el.getBoundingClientRect();
const elemTop = rect.top;
const elemBottom = rect.bottom;
// Only completely visible elements return true:
const isVisible = elemTop >= 0 && elemBottom <= window.innerHeight;
return isVisible;
}
React.useEffect(() => { React.useEffect(() => {
if (authenticated || !SHOW_ADS) { const shouldShowAds = SHOW_ADS && !authenticated;
return; // inject ad into last visible card
} injectAd(shouldShowAds);
(async () => {
// test if adblock is enabled
let adBlockEnabled = false;
const googleAdUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
try {
await fetch(new Request(googleAdUrl)).catch((_) => {
adBlockEnabled = true;
});
} catch (e) {
adBlockEnabled = true;
} finally {
if (!adBlockEnabled) {
// select the cards on page
let cards = document.getElementsByClassName('card claim-preview--tile');
// eslint-disable-next-line no-inner-declarations
function checkFlag() {
if (cards.length === 0) {
window.setTimeout(checkFlag, 100);
} else {
// find the last fully visible card
let lastCard;
// width of browser window
const windowWidth = window.innerWidth;
// on small screens, grab the second item
if (windowWidth <= 900) {
lastCard = cards[1];
} else {
// otherwise, get the last fully visible card
for (const card of cards) {
const isFullyVisible = isScrolledIntoView(card);
if (!isFullyVisible) break;
lastCard = card;
}
// if no last card was found, just exit the function to not cause errors
if (!lastCard) return;
}
// clone the last card
// $FlowFixMe
const clonedCard = lastCard.cloneNode(true);
// insert cloned card
// $FlowFixMe
lastCard.parentNode.insertBefore(clonedCard, lastCard);
// change the appearance of the cloned card
// $FlowFixMe
clonedCard.querySelector('.claim__menu-button').remove();
// $FlowFixMe
clonedCard.querySelector('.truncated-text').innerHTML = __(
'Hate these? Login to Odysee for an ad free experience'
);
// $FlowFixMe
clonedCard.querySelector('.claim-tile__info').remove();
// $FlowFixMe
clonedCard.querySelector('[role="none"]').removeAttribute('href');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.href = '/$/signin';
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('title');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard
.querySelector('.media__thumb')
.replaceWith(document.getElementsByClassName('homepageAdContainer')[0]);
// show the homepage ad which is not displayed at first
document.getElementsByClassName('homepageAdContainer')[0].style.display = 'block';
const thumbnail = window.getComputedStyle(lastCard.querySelector('.media__thumb'));
const styles = `#av-container, #AVcontent, #aniBox {
height: ${thumbnail.height} !important;
width: ${thumbnail.width} !important;
}`;
const styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.id = 'customAniviewStyling';
styleSheet.innerText = styles;
// $FlowFixMe
document.head.appendChild(styleSheet);
// delete last card to not introduce layout shifts
lastCard.remove();
}
}
checkFlag();
}
}
})();
}, []); }, []);
return ( return (

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import { selectTheme } from 'redux/selectors/settings'; import { selectTheme } from 'redux/selectors/settings';
import { makeSelectClaimForUri, selectClaimIsNsfwForUri } from 'redux/selectors/claims'; import { makeSelectClaimForUri, selectClaimIsNsfwForUri } from 'redux/selectors/claims';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUserVerifiedEmail } from 'redux/selectors/user';
import Ads from './view'; import Ads, { injectAd } from './view';
const select = (state, props) => ({ const select = (state, props) => ({
theme: selectTheme(state), theme: selectTheme(state),
@ -12,3 +12,4 @@ const select = (state, props) => ({
}); });
export default connect(select)(Ads); export default connect(select)(Ads);
export { injectAd };

View file

@ -36,7 +36,7 @@ type Props = {
claim: Claim, claim: Claim,
isMature: boolean, isMature: boolean,
authenticated: boolean, authenticated: boolean,
triggerBlacklist: boolean triggerBlacklist: boolean,
}; };
function removeIfExists(querySelector) { function removeIfExists(querySelector) {
@ -53,6 +53,8 @@ function Ads(props: Props) {
triggerBlacklist, triggerBlacklist,
} = props; } = props;
const shouldShowAds = SHOW_ADS && !authenticated;
// load ad and tags here // load ad and tags here
let scriptUrlToUse; let scriptUrlToUse;
let tagNameToUse; let tagNameToUse;
@ -71,7 +73,9 @@ function Ads(props: Props) {
// add script to DOM // add script to DOM
useEffect(() => { useEffect(() => {
if (SHOW_ADS && !authenticated) { if (isFirefoxAndroid) return;
if (shouldShowAds) {
let script; let script;
try { try {
script = document.createElement('script'); script = document.createElement('script');
@ -155,4 +159,128 @@ function Ads(props: Props) {
} }
} }
// returns true if passed element is fully visible on screen
function isScrolledIntoView(el) {
const rect = el.getBoundingClientRect();
const elemTop = rect.top;
const elemBottom = rect.bottom;
// Only completely visible elements return true:
const isVisible = elemTop >= 0 && elemBottom <= window.innerHeight;
return isVisible;
}
async function injectAd(shouldShowAds: boolean) {
// don't inject on firefox android or for authenticated users or no ads on instance
if (isFirefoxAndroid || !shouldShowAds) return;
// test if adblock is enabled
let adBlockEnabled = false;
const googleAdUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
try {
await fetch(new Request(googleAdUrl)).catch((_) => {
adBlockEnabled = true;
});
} catch (e) {
adBlockEnabled = true;
} finally {
if (!adBlockEnabled) {
// select the cards on page
let cards = document.getElementsByClassName('card claim-preview--tile');
// eslint-disable-next-line no-inner-declarations
function checkFlag() {
if (cards.length === 0) {
window.setTimeout(checkFlag, 100);
} else {
// find the last fully visible card
let lastCard;
// width of browser window
const windowWidth = window.innerWidth;
// on small screens, grab the second item
if (windowWidth <= 900) {
lastCard = cards[1];
} else {
// otherwise, get the last fully visible card
for (const card of cards) {
const isFullyVisible = isScrolledIntoView(card);
if (!isFullyVisible) break;
lastCard = card;
}
// if no last card was found, just exit the function to not cause errors
if (!lastCard) return;
}
// clone the last card
// $FlowFixMe
const clonedCard = lastCard.cloneNode(true);
// insert cloned card
// $FlowFixMe
lastCard.parentNode.insertBefore(clonedCard, lastCard);
// change the appearance of the cloned card
// $FlowFixMe
clonedCard.querySelector('.claim__menu-button').remove();
// $FlowFixMe
clonedCard.querySelector('.truncated-text').innerHTML = __(
'Hate these? Login to Odysee for an ad free experience'
);
// $FlowFixMe
clonedCard.querySelector('.claim-tile__info').remove();
// $FlowFixMe
clonedCard.querySelector('[role="none"]').removeAttribute('href');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.href = '/$/signin';
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__title').firstChild.removeAttribute('title');
// $FlowFixMe
clonedCard.querySelector('.claim-tile__header').firstChild.removeAttribute('aria-label');
// $FlowFixMe
clonedCard
.querySelector('.media__thumb')
.replaceWith(document.getElementsByClassName('homepageAdContainer')[0]);
// show the homepage ad which is not displayed at first
document.getElementsByClassName('homepageAdContainer')[0].style.display = 'block';
const thumbnail = window.getComputedStyle(lastCard.querySelector('.media__thumb'));
const styles = `#av-container, #AVcontent, #aniBox {
height: ${thumbnail.height} !important;
width: ${thumbnail.width} !important;
}`;
const styleSheet = document.createElement('style');
styleSheet.type = 'text/css';
styleSheet.id = 'customAniviewStyling';
styleSheet.innerText = styles;
// $FlowFixMe
document.head.appendChild(styleSheet);
// delete last card to not introduce layout shifts
lastCard.remove();
// addresses bug where ad doesn't show up until a scroll event
document.dispatchEvent(new CustomEvent('scroll'));
}
}
checkFlag();
}
}
}
export default withRouter(Ads); export default withRouter(Ads);
export { injectAd };