Add ad to the homepage as a card (#362)
* coming along well * coming along well * adding custom react element * coming along well * coming along well * coming along well * working pretty well * almost done * essentially working just could use a couple touchups * cleanup and lint errors * fix lint errors * fix flow errors * possible bugfix * dynamically set width and height * only run when rowdata is populated * trying using ref * better way to check for card population * working implementation * working implementation * clean up flow and clean up script * fix typo in comment and logs
This commit is contained in:
parent
873ac4dc5d
commit
1e071550ae
2 changed files with 172 additions and 33 deletions
|
@ -1,8 +1,9 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import * as PAGES from 'constants/pages';
|
||||
import { SITE_NAME, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||
import React from 'react';
|
||||
import { SHOW_ADS, SITE_NAME, SIMPLE_SITE, ENABLE_NO_SOURCE_CLAIMS } from 'config';
|
||||
import Ads from 'web/component/ads';
|
||||
import React from 'react';
|
||||
import Page from 'component/page';
|
||||
import Button from 'component/button';
|
||||
import ClaimTilesDiscover from 'component/claimTilesDiscover';
|
||||
|
@ -74,6 +75,7 @@ function HomePage(props: Props) {
|
|||
|
||||
return (
|
||||
<div key={title} className="claim-grid__wrapper">
|
||||
{/* category header */}
|
||||
{index !== 0 && title && typeof title === 'string' && (
|
||||
<h1 className="claim-grid__header">
|
||||
<Button navigate={route || link} button="link">
|
||||
|
@ -91,6 +93,7 @@ function HomePage(props: Props) {
|
|||
</WaitUntilOnPage>
|
||||
)}
|
||||
|
||||
{/* view more button */}
|
||||
{(route || link) && (
|
||||
<Button
|
||||
className="claim-grid__title--secondary"
|
||||
|
@ -108,6 +111,135 @@ function HomePage(props: Props) {
|
|||
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(() => {
|
||||
if (authenticated || !SHOW_ADS) {
|
||||
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;
|
||||
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;
|
||||
|
||||
var styles = `#av-container, #AVcontent, #aniBox {
|
||||
height: ${imageHeight} !important;
|
||||
width: ${imageWidth} !important;
|
||||
}`;
|
||||
|
||||
var styleSheet = document.createElement('style');
|
||||
styleSheet.type = 'text/css';
|
||||
styleSheet.innerText = styles;
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(styleSheet);
|
||||
|
||||
clonedCard.style.display = 'none';
|
||||
|
||||
let timeoutCount = 0;
|
||||
// eslint-disable-next-line no-inner-declarations
|
||||
function checkForAniview() {
|
||||
const aniBoxDiv = document.getElementsByClassName('homepageAdContainer')[0].querySelector('#aniBox');
|
||||
|
||||
if (!aniBoxDiv) {
|
||||
timeoutCount += 100;
|
||||
if (timeoutCount < 500) {
|
||||
window.setTimeout(checkForAniview, 100);
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
clonedCard.style.display = 'block';
|
||||
}
|
||||
}
|
||||
checkForAniview();
|
||||
}
|
||||
}
|
||||
checkFlag();
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Page fullWidthPage>
|
||||
{!SIMPLE_SITE && (authenticated || !IS_WEB) && !subscribedChannels.length && (
|
||||
|
@ -126,6 +258,7 @@ function HomePage(props: Props) {
|
|||
)}
|
||||
{/* @if TARGET='web' */}
|
||||
{SIMPLE_SITE && <Meme />}
|
||||
<Ads type="homepage" />
|
||||
{/* @endif */}
|
||||
{rowData.map(({ title, route, link, icon, help, pinnedUrls: pinUrls, options = {} }, index) => {
|
||||
// add pins here
|
||||
|
|
|
@ -6,9 +6,6 @@ import { withRouter } from 'react-router';
|
|||
import I18nMessage from 'component/i18nMessage';
|
||||
import Button from 'component/button';
|
||||
import classnames from 'classnames';
|
||||
// $FlowFixMe
|
||||
|
||||
const IS_MOBILE = typeof window.orientation !== 'undefined';
|
||||
|
||||
const ADS_URL = 'https://cdn.vidcrunch.com/integrations/618bb4d28aac298191eec411/Lbry_Odysee.com_Responsive_Floating_DFP_Rev70_1011.js';
|
||||
const ADS_TAG = 'vidcrunchJS537102317';
|
||||
|
@ -16,6 +13,9 @@ const ADS_TAG = 'vidcrunchJS537102317';
|
|||
const IOS_ADS_URL = 'https://cdn.vidcrunch.com/integrations/618bb4d28aac298191eec411/Lbry_Odysee.com_Mobile_Floating_DFP_Rev70_1611.js';
|
||||
const IOS_ADS_TAG = 'vidcrunchJS199212779';
|
||||
|
||||
const HOMEPAGE_ADS_URL = 'https://cdn.vidcrunch.com/integrations/618bb4d28aac298191eec411/Lbry_Odysee.com_Responsive_Floating_300x169_DFP_Rev70_1211.js';
|
||||
const HOMEPAGE_ADS_TAG = 'vidcrunchJS330442776';
|
||||
|
||||
const IS_IOS =
|
||||
(/iPad|iPhone|iPod/.test(navigator.platform) ||
|
||||
// for iOS 13+ , platform is MacIntel, so use this to test
|
||||
|
@ -33,22 +33,29 @@ type Props = {
|
|||
function Ads(props: Props) {
|
||||
const {
|
||||
location: { pathname },
|
||||
type = 'sidebar',
|
||||
type = 'video',
|
||||
small,
|
||||
} = props;
|
||||
|
||||
// load ad and tags here
|
||||
let scriptUrlToUse;
|
||||
let tagNameToUse;
|
||||
if (IS_IOS) {
|
||||
tagNameToUse = IOS_ADS_TAG;
|
||||
scriptUrlToUse = IOS_ADS_URL;
|
||||
} else {
|
||||
tagNameToUse = ADS_TAG;
|
||||
scriptUrlToUse = ADS_URL;
|
||||
if (type === 'video') {
|
||||
if (IS_IOS) {
|
||||
tagNameToUse = IOS_ADS_TAG;
|
||||
scriptUrlToUse = IOS_ADS_URL;
|
||||
} else {
|
||||
tagNameToUse = ADS_TAG;
|
||||
scriptUrlToUse = ADS_URL;
|
||||
}
|
||||
} else if (type === 'homepage') {
|
||||
tagNameToUse = HOMEPAGE_ADS_TAG;
|
||||
scriptUrlToUse = HOMEPAGE_ADS_URL;
|
||||
}
|
||||
|
||||
// add script to DOM
|
||||
useEffect(() => {
|
||||
if (SHOW_ADS && type === 'video') {
|
||||
if (SHOW_ADS) {
|
||||
let script;
|
||||
try {
|
||||
let fjs = document.getElementsByTagName('script')[0];
|
||||
|
@ -56,30 +63,18 @@ function Ads(props: Props) {
|
|||
script.src = scriptUrlToUse;
|
||||
// $FlowFixMe
|
||||
fjs.parentNode.insertBefore(script, fjs);
|
||||
|
||||
return () => {
|
||||
// $FlowFixMe
|
||||
document.head.removeChild(script);
|
||||
};
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// TODO: remove the script when it exists?
|
||||
}, [type]);
|
||||
|
||||
useEffect(() => {
|
||||
if (SHOW_ADS && !IS_MOBILE && type === 'sidebar') {
|
||||
const script = document.createElement('script');
|
||||
script.src = ADS_URL;
|
||||
script.defer = true;
|
||||
// $FlowFixMe
|
||||
document.body.appendChild(script);
|
||||
return () => {
|
||||
// $FlowFixMe
|
||||
document.body.removeChild(script);
|
||||
// if user navigates too rapidly, <style> tags can build up
|
||||
// $FlowFixMe
|
||||
if (document.body.getElementsByTagName('style').length) {
|
||||
// $FlowFixMe
|
||||
document.body.getElementsByTagName('style')[0].remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
}, [type]);
|
||||
|
||||
// display to say "sign up to not see these"
|
||||
const adsSignInDriver = (
|
||||
<I18nMessage
|
||||
tokens={{
|
||||
|
@ -96,6 +91,7 @@ function Ads(props: Props) {
|
|||
</I18nMessage>
|
||||
);
|
||||
|
||||
// ad shown in the related videos area
|
||||
const videoAd = (
|
||||
<div className="ads__claim-item">
|
||||
<div id={tagNameToUse} className="ads__injected-video" style={{display: 'none'}} />
|
||||
|
@ -110,12 +106,22 @@ function Ads(props: Props) {
|
|||
</div>
|
||||
);
|
||||
|
||||
// homepage ad in a card
|
||||
const homepageCardAd = (
|
||||
<div className="homepageAdContainer media__thumb" style={{display: 'none'}}>
|
||||
<div id={tagNameToUse} className="homepageAdDiv media__thumb" style={{display: 'none'}} />
|
||||
</div>
|
||||
);
|
||||
|
||||
if (!SHOW_ADS) {
|
||||
return false;
|
||||
}
|
||||
if (type === 'video') {
|
||||
return videoAd;
|
||||
}
|
||||
if (type === 'homepage') {
|
||||
return homepageCardAd;
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(Ads);
|
||||
|
|
Loading…
Reference in a new issue