From f112dd980ba1923279d76f50945aad5633ef5bc7 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 1 Aug 2022 18:50:46 -0500 Subject: [PATCH] AdProvider boilerplate --- app/soapbox/features/ads/providers/index.ts | 17 +++++++++++++++++ .../features/ads/providers/soapbox-config.ts | 14 ++++++++++++++ app/soapbox/normalizers/index.ts | 1 + app/soapbox/normalizers/soapbox/ad.ts | 19 +++++++++++++++++++ .../normalizers/soapbox/soapbox_config.ts | 10 ++++++++++ app/soapbox/types/soapbox.ts | 3 +++ 6 files changed, 64 insertions(+) create mode 100644 app/soapbox/features/ads/providers/index.ts create mode 100644 app/soapbox/features/ads/providers/soapbox-config.ts create mode 100644 app/soapbox/normalizers/soapbox/ad.ts diff --git a/app/soapbox/features/ads/providers/index.ts b/app/soapbox/features/ads/providers/index.ts new file mode 100644 index 000000000..3adf323c7 --- /dev/null +++ b/app/soapbox/features/ads/providers/index.ts @@ -0,0 +1,17 @@ +import type { RootState } from 'soapbox/store'; +import type { Card } from 'soapbox/types/entities'; + +/** Ad server implementation. */ +interface AdProvider { + getAds(getState: () => RootState): Promise, +} + +/** Entity representing an advertisement. */ +interface Ad { + /** Ad data in Card (OEmbed-ish) format. */ + card: Card, + /** Impression URL to fetch when displaying the ad. */ + impression?: string, +} + +export type { Ad, AdProvider }; diff --git a/app/soapbox/features/ads/providers/soapbox-config.ts b/app/soapbox/features/ads/providers/soapbox-config.ts new file mode 100644 index 000000000..21163729c --- /dev/null +++ b/app/soapbox/features/ads/providers/soapbox-config.ts @@ -0,0 +1,14 @@ +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; + +import type { AdProvider } from '.'; + +/** Provides ads from Soapbox Config. */ +const SoapboxConfigAdProvider: AdProvider = { + getAds: async(getState) => { + const state = getState(); + const soapboxConfig = getSoapboxConfig(state); + return soapboxConfig.ads.toArray(); + }, +}; + +export default SoapboxConfigAdProvider; diff --git a/app/soapbox/normalizers/index.ts b/app/soapbox/normalizers/index.ts index d25cbd014..9fdc04f68 100644 --- a/app/soapbox/normalizers/index.ts +++ b/app/soapbox/normalizers/index.ts @@ -20,4 +20,5 @@ export { StatusRecord, normalizeStatus } from './status'; export { StatusEditRecord, normalizeStatusEdit } from './status_edit'; export { TagRecord, normalizeTag } from './tag'; +export { AdRecord, normalizeAd } from './soapbox/ad'; export { SoapboxConfigRecord, normalizeSoapboxConfig } from './soapbox/soapbox_config'; diff --git a/app/soapbox/normalizers/soapbox/ad.ts b/app/soapbox/normalizers/soapbox/ad.ts new file mode 100644 index 000000000..c29ee9a3e --- /dev/null +++ b/app/soapbox/normalizers/soapbox/ad.ts @@ -0,0 +1,19 @@ +import { + Map as ImmutableMap, + Record as ImmutableRecord, + fromJS, +} from 'immutable'; + +import { CardRecord, normalizeCard } from '../card'; + +export const AdRecord = ImmutableRecord({ + card: CardRecord(), + impression: undefined as string | undefined, +}); + +/** Normalizes an ad from Soapbox Config. */ +export const normalizeAd = (ad: Record) => { + const map = ImmutableMap(fromJS(ad)); + const card = normalizeCard(map.get('card')); + return AdRecord(map.set('card', card)); +}; diff --git a/app/soapbox/normalizers/soapbox/soapbox_config.ts b/app/soapbox/normalizers/soapbox/soapbox_config.ts index d90112810..0314771fe 100644 --- a/app/soapbox/normalizers/soapbox/soapbox_config.ts +++ b/app/soapbox/normalizers/soapbox/soapbox_config.ts @@ -9,7 +9,10 @@ import trimStart from 'lodash/trimStart'; import { toTailwind } from 'soapbox/utils/tailwind'; import { generateAccent } from 'soapbox/utils/theme'; +import { normalizeAd } from './ad'; + import type { + Ad, PromoPanelItem, FooterItem, CryptoAddress, @@ -78,6 +81,7 @@ export const CryptoAddressRecord = ImmutableRecord({ }); export const SoapboxConfigRecord = ImmutableRecord({ + ads: ImmutableList(), appleAppId: null, logo: '', logoDarkMode: null, @@ -122,6 +126,11 @@ export const SoapboxConfigRecord = ImmutableRecord({ type SoapboxConfigMap = ImmutableMap; +const normalizeAds = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => { + const ads = ImmutableList>(soapboxConfig.get('ads')); + return soapboxConfig.set('ads', ads.map(normalizeAd)); +}; + const normalizeCryptoAddress = (address: unknown): CryptoAddress => { return CryptoAddressRecord(ImmutableMap(fromJS(address))).update('ticker', ticker => { return trimStart(ticker, '$').toLowerCase(); @@ -186,6 +195,7 @@ export const normalizeSoapboxConfig = (soapboxConfig: Record) => { normalizeFooterLinks(soapboxConfig); maybeAddMissingColors(soapboxConfig); normalizeCryptoAddresses(soapboxConfig); + normalizeAds(soapboxConfig); }), ); }; diff --git a/app/soapbox/types/soapbox.ts b/app/soapbox/types/soapbox.ts index 32c2f681c..1a37d1a88 100644 --- a/app/soapbox/types/soapbox.ts +++ b/app/soapbox/types/soapbox.ts @@ -1,3 +1,4 @@ +import { AdRecord } from 'soapbox/normalizers/soapbox/ad'; import { PromoPanelItemRecord, FooterItemRecord, @@ -7,6 +8,7 @@ import { type Me = string | null | false | undefined; +type Ad = ReturnType; type PromoPanelItem = ReturnType; type FooterItem = ReturnType; type CryptoAddress = ReturnType; @@ -14,6 +16,7 @@ type SoapboxConfig = ReturnType; export { Me, + Ad, PromoPanelItem, FooterItem, CryptoAddress,