{"version":3,"file":"js/85943-07fb3a15157eb0ada44b.js","mappings":"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","sources":["webpack://StravaModern/./app/javascript/api/athlete/athlete.js","webpack://StravaModern/./app/javascript/components/EmailVerificationCTA/index.scss?534f","webpack://StravaModern/./app/javascript/components/EmailVerificationCTA/index.js","webpack://StravaModern/./app/javascript/components/EmailVerificationCTA/placements/NotificationEmailVerificationCTA/index.scss?ffba","webpack://StravaModern/./app/javascript/components/EmailVerificationCTA/placements/NotificationEmailVerificationCTA/index.js","webpack://StravaModern/./app/javascript/components/StravaAlert/StravaAlert.scss?a1ac","webpack://StravaModern/./app/javascript/components/StravaAlert/StravaAlert.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsButton/InviteFriendsButton.scss?21f1","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/constants/invite-friends-constants.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/utils/invite-friends-utils.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/InviteFriendsModal.scss?143d","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/state/InviteFriendsContext.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/state/InviteFriends.actions.js","webpack://StravaModern/./app/javascript/hooks/externalSocialPartners/useGoogle.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/EmailTabContent.scss?f2d3","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/LinkGoogleAccount/LinkGoogleAccount.scss?841b","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/LinkGoogleAccount/LinkGoogleAccount.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/GmailContactList/GmailContactList.scss?0bdd","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/GmailContactList/components/ContactEntry.scss?f7d7","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/EmailTabContent.utils.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/GmailContactList/components/ContactEntry.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/components/GmailContactList/GmailContactList.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/components/EmailTabContent/EmailTabContent.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsModal/InviteFriendsModal.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/state/InviteFriends.reducer.js","webpack://StravaModern/./app/javascript/components/shared/InviteFriends/components/InviteFriendsButton/InviteFriendsButton.js","webpack://StravaModern/./app/javascript/components/shared/Modal/styles.scss?227e","webpack://StravaModern/./app/javascript/components/shared/Modal/index.js","webpack://StravaModern/./app/javascript/hooks/externalSocialPartners/useFacebook.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/LinkFacebookButton/LinkFacebookButton.scss?235a","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/LinkFacebookButton/LinkFacebookButton.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/LinkFacebookAccount/LinkFacebookAccount.scss?b824","webpack://StravaModern/./app/javascript/components/shared/friends/components/LinkFacebookAccount/LinkFacebookAccount.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/FacebookFriendList/InviteFriendsHeader/InviteFriendsHeader.scss?9139","webpack://StravaModern/./app/javascript/components/shared/friends/components/FacebookFriendList/InviteFriendsHeader/InviteFriendsHeader.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/FacebookFriendList/FacebookFriendList.js","webpack://StravaModern/./app/javascript/components/shared/friends/FindFacebookFriends/FindFacebookFriends.scss?ea55","webpack://StravaModern/./app/javascript/components/shared/friends/FindFacebookFriends/FindFacebookFriends.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/FriendList/FriendList.scss?6e23","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/FriendList/FriendList.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/AthleteInfo/AthleteInfo.scss?a41a","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/AthleteInfo/AthleteInfo.js","webpack://StravaModern/./app/javascript/components/shared/friends/utils/useCtaAction.js","webpack://StravaModern/./app/javascript/components/shared/friends/components/shared/FriendListItem/FriendListItem.js","webpack://StravaModern/./app/javascript/components/shared/friends/state/FriendsContext.js","webpack://StravaModern/./app/javascript/components/shared/friends/state/friendsActions.js","webpack://StravaModern/./app/javascript/components/shared/friends/state/friendsReducer.js","webpack://StravaModern/./app/javascript/components/shared/friends/utils/friendsConstants.js","webpack://StravaModern/./app/javascript/components/shared/friends/utils/friendsUtils.js","webpack://StravaModern/./app/javascript/constants/alerts/alert-types.js","webpack://StravaModern/./app/javascript/constants/follows/following-constants.js","webpack://StravaModern/./app/javascript/externalSocialPartners.js","webpack://StravaModern/./app/javascript/hooks/externalSocialPartners/constants/auth-status-constants.js","webpack://StravaModern/./app/javascript/utils/generalUtils.js","webpack://StravaModern/./app/javascript/utils/networking-client.js"],"sourcesContent":["import createNetworkingClient from 'utils/networking-client';\nimport { StatusCodes } from 'http-status-codes';\nimport { FOLLOWING_STATUS } from '../../constants/follows/following-constants';\nimport { logError } from '../../utils/sentry';\n\n/**\n * Follows an athlete on strava.\n *\n * @param {Object} param\n * @param {string} param.followerId - id for the athlete who is requesting the follow\n * @param {string} param.followingId - id for the athlete to be followed\n * @returns {Promise} - enum value PENDING or FOLLOWING\n */\nexport const followAthlete = ({ followerId, followingId }) => {\n return new Promise((resolve) => {\n createNetworkingClient()\n .post(`/athletes/${followerId}/follows`, {\n follow: {\n follower_id: followerId,\n following_id: followingId\n }\n })\n .then((response) => {\n if (response?.status === StatusCodes.OK) {\n const { data } = response;\n if (data.approved) {\n resolve(FOLLOWING_STATUS.following);\n } else {\n resolve(FOLLOWING_STATUS.pending);\n }\n } else {\n resolve(FOLLOWING_STATUS.error);\n // TODO log sentry error\n }\n })\n .catch(() => {\n resolve(FOLLOWING_STATUS.error);\n // TODO log sentry error\n });\n });\n};\n\nexport const bulkFollow = ({ followeeIds }) => {\n return new Promise((resolve) => {\n createNetworkingClient()\n .post('/athlete/bulk_follow', {\n followee_ids: followeeIds\n })\n .then((response) => {\n const { success, followed_athlete_ids: ids } = response.data;\n resolve({ success, followedAthleteIds: ids || [] });\n })\n .catch((e) => {\n logError(e);\n resolve({ success: false });\n });\n });\n};\n\nexport const unfollowAthlete = ({ followerId, followingId }) => {\n return new Promise((resolve) => {\n createNetworkingClient()\n .delete(\n `/athletes/${followerId}/follows/${followingId}`,\n {\n data: {\n follow: {\n follower_id: followerId,\n following_id: followingId\n }\n }\n },\n { headers: { Accept: 'text/javascript' } }\n )\n .then((response) => {\n if (response?.status === StatusCodes.NO_CONTENT) {\n resolve(true);\n } else {\n logError(response);\n resolve(false);\n }\n })\n .catch((e) => {\n logError(e);\n resolve(false);\n });\n });\n};\n\n/**\n * Gets suggested follow list\n *\n * @param {Object} param\n * @param {string} param.callsite - source making the get request\n * @returns {Promise} - list of suggested friends to follow\n */\nexport const getSuggestedFollows = ({ callsite }) => {\n return new Promise((resolve, reject) => {\n createNetworkingClient()\n .get('/athlete/suggested_follows', {\n params: { callsite }\n })\n .then((response) => {\n if (response?.status === StatusCodes.OK) {\n const { data } = response;\n resolve(data);\n } else {\n logError(response.error);\n resolve(response.error);\n }\n })\n .catch((e) => {\n logError(e);\n reject(e);\n });\n });\n};\n\nexport default { followAthlete, unfollowAthlete, getSuggestedFollows };\n","// extracted by mini-css-extract-plugin\nexport default {\"cta\":\"EmailVerificationCTA--cta--oTXkG\",\"dialog\":\"EmailVerificationCTA--dialog--QyyTh\",\"modal\":\"EmailVerificationCTA--modal--Lg4o7\",\"close-button\":\"EmailVerificationCTA--close-button--50iQm\",\"closeButton\":\"EmailVerificationCTA--close-button--50iQm\",\"confirm-email-icon\":\"EmailVerificationCTA--confirm-email-icon--zCSY9\",\"confirmEmailIcon\":\"EmailVerificationCTA--confirm-email-icon--zCSY9\",\"email-text\":\"EmailVerificationCTA--email-text--1aDgC\",\"emailText\":\"EmailVerificationCTA--email-text--1aDgC\",\"wrong-email-text\":\"EmailVerificationCTA--wrong-email-text--iT4r+\",\"wrongEmailText\":\"EmailVerificationCTA--wrong-email-text--iT4r+\"};","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport I18n from 'utils/I18n';\nimport createNetworkingClient from 'utils/networking-client';\n\nimport Modal from 'components/shared/Modal';\n\nimport styles from './index.scss';\n\nconst I18nCloseModal = 'strava.settings.email_verification.close_modal';\nconst I18nHeadline = 'strava.settings.email_verification.headline';\nconst I18nPrompt = 'strava.settings.email_verification.prompt_html';\nconst I18nResendEmail = 'strava.settings.email_verification.resend_email_cta';\nconst I18nWrongEmail = 'strava.settings.email_verification.wrong_email_html';\n\nconst UrlResendVerificationEmail = '/athlete/resend_email';\nconst UrlChangeEmail = '/settings/email_change';\n\nclass EmailVerificationCTA extends React.Component {\n state = {\n modalIsOpen: false,\n resendEmailInProgress: false\n };\n\n componentDidMount() {\n if (this.props.resendOnMount) {\n this.resendEmail();\n }\n }\n\n /**\n * resendEmail will attempt to send another verification email to the athlete\n * and pop the success modal.\n *\n * - there is a lock around the operation.\n * - if the request fails the lock is removed but the modal is not popped\n */\n resendEmail = () => {\n const { resendEmailInProgress } = this.state;\n\n if (resendEmailInProgress) return;\n this.setState({ resendEmailInProgress: true });\n createNetworkingClient()\n .post(UrlResendVerificationEmail)\n .then(() =>\n this.setState({ modalIsOpen: true, resendEmailInProgress: false })\n )\n .catch(() => {\n this.setState({ resendEmailInProgress: false });\n }); // set here instead of finally due to FF polyfill issue\n };\n\n closeModal = () => {\n this.setState({ modalIsOpen: false });\n };\n\n render() {\n const { modalIsOpen } = this.state;\n const { children, className, email, optionalExplanation } = this.props;\n\n const cta = children ? (\n \n ) : (\n \n {I18n.t(I18nResendEmail)}\n \n );\n\n return (\n <>\n {cta}\n \n
\n \n
\n \n
\n
\n

{I18n.t(I18nHeadline)}

\n {optionalExplanation && (\n

\n {optionalExplanation}\n

\n )}\n

\n {I18n.t_html(I18nPrompt, {\n pending_email: email,\n class_name: styles.emailText\n })}\n

\n
\n

\n {I18n.t_html(I18nWrongEmail, {\n email_settings_path: UrlChangeEmail\n })}\n

\n
\n
\n \n \n );\n }\n}\n\nEmailVerificationCTA.propTypes = {\n children: PropTypes.node,\n className: PropTypes.string,\n email: PropTypes.string.isRequired,\n resendOnMount: PropTypes.bool,\n optionalExplanation: PropTypes.string\n};\n\nEmailVerificationCTA.defaultProps = {\n children: null,\n className: '',\n resendOnMount: false,\n optionalExplanation: ''\n};\n\nexport default EmailVerificationCTA;\n","// extracted by mini-css-extract-plugin\nexport default {\"wrapper\":\"NotificationEmailVerificationCTA--wrapper--oW7Ds\",\"text-caption\":\"NotificationEmailVerificationCTA--text-caption--maR6G\",\"textCaption\":\"NotificationEmailVerificationCTA--text-caption--maR6G\"};","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport EmailVerificationCTA from 'components/EmailVerificationCTA';\n\nimport styles from './index.scss';\n\nfunction NotificationEmailVerificationCTA({ className, email, iconURL, text }) {\n return (\n \n \n
{text}
\n \n );\n}\n\nNotificationEmailVerificationCTA.propTypes = {\n className: PropTypes.string,\n email: PropTypes.string.isRequired,\n iconURL: PropTypes.string.isRequired,\n text: PropTypes.string.isRequired\n};\n\nNotificationEmailVerificationCTA.defaultProps = {\n className: ''\n};\n\nexport default NotificationEmailVerificationCTA;\n","// extracted by mini-css-extract-plugin\nexport default {\"alert\":\"StravaAlert--alert--0tRrZ\",\"error\":\"StravaAlert--error--Cha6i\",\"success\":\"StravaAlert--success--52fm+\",\"warning\":\"StravaAlert--warning--JQQmd\",\"info\":\"StravaAlert--info---apjx\"};","import React from 'react';\nimport Alert from '@reach/alert';\nimport PropTypes from 'prop-types';\nimport clsx from '@strava/ui/clsx';\nimport { ALERT_TYPES } from 'constants/alerts/alert-types';\nimport styles from './StravaAlert.scss';\n\nconst StravaAlert = ({ children, className, severity, ...options }) => {\n return (\n \n {children}\n \n );\n};\n\nStravaAlert.defaultProps = {\n className: null\n};\n\nStravaAlert.propTypes = {\n severity: PropTypes.oneOf(Object.values(ALERT_TYPES)).isRequired,\n children: PropTypes.node.isRequired,\n className: PropTypes.string\n};\n\nexport default StravaAlert;\n","// extracted by mini-css-extract-plugin\nexport default {\"dashboard-sidebar\":\"InviteFriendsButton--dashboard-sidebar--BoJFT\",\"dashboardSidebar\":\"InviteFriendsButton--dashboard-sidebar--BoJFT\",\"onboarding\":\"InviteFriendsButton--onboarding--8znw0\",\"header-menu\":\"InviteFriendsButton--header-menu--VJUik\",\"headerMenu\":\"InviteFriendsButton--header-menu--VJUik\"};","export const I18nPrefix = 'components.invite_your_friends';\n\nexport default { I18nPrefix };\n","import I18n from 'utils/I18n';\nimport { I18nPrefix } from '../constants/invite-friends-constants';\n\nexport const t = (key, params) => I18n.t(`${I18nPrefix}.${key}`, { ...params });\n\nexport default { t };\n","// extracted by mini-css-extract-plugin\nexport default {\"tab-panels\":\"InviteFriendsModal--tab-panels--04Cpi\",\"tabPanels\":\"InviteFriendsModal--tab-panels--04Cpi\",\"tab-list\":\"InviteFriendsModal--tab-list--ClIK5\",\"tabList\":\"InviteFriendsModal--tab-list--ClIK5\"};","import React from 'react';\n\nconst InviteFriendsContext = React.createContext();\n// Context object accepts a displayName string property.\n// React DevTools uses this string to determine what to display for the context.\nInviteFriendsContext.displayName = 'InviteFriendsContext';\n\nexport function useInviteFriendsContext() {\n return React.useContext(InviteFriendsContext);\n}\n\nexport default InviteFriendsContext;\n","export const ADD_ALERT = 'ADD_ALERT';\nexport const CHANGE_TAB = 'CHANGE_TAB';\nexport const CLEAR_ALERT = 'CLEAR_ALERT';\nexport const CLEAR_EMAILS = 'CLEAR_EMAILS';\nexport const CLOSE_MODAL = 'CLOSE_MODAL';\nexport const OPEN_MODAL = 'OPEN_MODAL';\nexport const UPDATE_EMAILS = 'UPDATE_EMAILS';\nexport const UPDATE_FB_FRIENDS = 'UPDATE_FB_FRIENDS';\nexport const UPDATE_FB_FRIEND_FOLLOWING_STATUS =\n 'UPDATE_FB_FRIEND_FOLLOWING_STATUS';\nexport const UPDATE_INVITED_EMAILS_LIST = 'UPDATE_INVITED_EMAILS_LIST';\n\nexport default {\n ADD_ALERT,\n CHANGE_TAB,\n CLEAR_ALERT,\n CLOSE_MODAL,\n OPEN_MODAL,\n UPDATE_EMAILS,\n UPDATE_FB_FRIENDS,\n UPDATE_FB_FRIEND_FOLLOWING_STATUS,\n UPDATE_INVITED_EMAILS_LIST\n};\n","import { isNil } from 'lodash-es';\nimport { useEffect, useState } from 'react';\nimport createNetworkingClient from 'utils/networking-client';\nimport { injectGoogleScript } from 'externalSocialPartners';\nimport { timeout } from 'utils/devUtils';\nimport { AuthorizationStatus } from './constants/auth-status-constants';\nimport { logError } from '../../utils/sentry';\n\nconst PEOPLE_BASE_URL = 'https://people.googleapis.com/v1/';\n\n/**\n * Fetches a list of contacts from an authenticated google account.\n */\nconst useGoogle = ({ clientId, mocked = false }) => {\n const [contacts, setContacts] = useState([]);\n const [token, setToken] = useState(undefined);\n const [authorizationStatus, setAuthorizationStatus] = useState(\n AuthorizationStatus.INITIATED\n );\n\n const mockedConnections = () => {\n return new Promise((resolve) => {\n import('./data/google_connections_sample.json').then(async (c) => {\n await timeout(2000); // delaying things on purpose so we can see the spinner when mocking data\n resolve(c.connections);\n });\n });\n };\n\n /**\n * callback method called when the athlete signs into their google account.\n * This method attempts to retrieve contacts from the authenticated google account.\n */\n const handleSignInContactsScope = (tokenResponse) => {\n if (tokenResponse && tokenResponse.access_token) {\n const accessToken = tokenResponse.access_token;\n setToken(accessToken);\n\n // TODO [fumba] - change the scope to https://www.googleapis.com/auth/contacts.readonly\n // once strava app is verified by google.\n const requestedScope = 'https://www.googleapis.com/auth/userinfo.profile';\n if (\n window.google.accounts.oauth2.hasGrantedAllScopes(\n tokenResponse,\n requestedScope\n )\n ) {\n const headers = { Authorization: `Bearer ${accessToken}` };\n const url = mocked\n ? 'https://www.googleapis.com/oauth2/v3/userinfo'\n : `${PEOPLE_BASE_URL}people/me/connections?personFields=names,photos,emailAddresses`;\n\n setAuthorizationStatus(AuthorizationStatus.AUTHORIZED);\n createNetworkingClient({ headers })\n .get(url, { params: { alt: 'json' } })\n .then(async (response) => {\n if (response && response.status === 200) {\n let { connections } = response.data;\n if (mocked) {\n connections = await mockedConnections();\n }\n setContacts(connections);\n setAuthorizationStatus(AuthorizationStatus.DATA_FETCHED);\n } else {\n setAuthorizationStatus(AuthorizationStatus.ERROR);\n logError(response.error);\n }\n })\n .catch((e) => {\n setAuthorizationStatus(AuthorizationStatus.ERROR);\n logError(e);\n });\n } else {\n // unauthorized\n setAuthorizationStatus(AuthorizationStatus.UNAUTHORIZED);\n window.google.accounts.oauth2.revoke(accessToken);\n }\n }\n };\n\n /**\n * Initializes a client that is used by athletes to request a token\n */\n const initializeGsiTokenClient = (scope, callback) => {\n const client = window.google.accounts.oauth2.initTokenClient({\n client_id: clientId,\n scope,\n callback\n });\n return client;\n };\n\n /**\n * injects GSI javascript library when the component that uses this hook is mounted\n */\n useEffect(() => {\n injectGoogleScript(async () => {\n if (mocked) {\n await timeout(2000);\n }\n setAuthorizationStatus(AuthorizationStatus.READY);\n });\n\n return () => {\n window.google.accounts.id.cancel();\n };\n }, [mocked]);\n\n const requestContacts = () => {\n setAuthorizationStatus(AuthorizationStatus.READY);\n setContacts([]);\n\n // TODO [fumba] - change the scope to https://www.googleapis.com/auth/contacts.readonly\n // once strava app is verified by google.\n const requestedScope = 'https://www.googleapis.com/auth/userinfo.profile';\n\n const client = initializeGsiTokenClient(\n requestedScope,\n handleSignInContactsScope\n );\n client.requestAccessToken();\n };\n\n const disconnect = () => {\n setContacts([]);\n setAuthorizationStatus(AuthorizationStatus.READY);\n if (!isNil(token)) {\n window.google.accounts.oauth2.revoke(token);\n }\n };\n\n return {\n authorizationStatus,\n contacts,\n requestContacts,\n disconnect\n };\n};\n\nexport default useGoogle;\n","// extracted by mini-css-extract-plugin\nexport default {\"flex-grid\":\"EmailTabContent--flex-grid--Mga-F\",\"flexGrid\":\"EmailTabContent--flex-grid--Mga-F\",\"col\":\"EmailTabContent--col--QG6K6\",\"email-column\":\"EmailTabContent--email-column--C8DUs\",\"emailColumn\":\"EmailTabContent--email-column--C8DUs\",\"email-input\":\"EmailTabContent--email-input--Xkzv2\",\"emailInput\":\"EmailTabContent--email-input--Xkzv2\",\"email-body\":\"EmailTabContent--email-body--lNZfZ\",\"emailBody\":\"EmailTabContent--email-body--lNZfZ\",\"headline\":\"EmailTabContent--headline--wy3OM\",\"email-validation-error\":\"EmailTabContent--email-validation-error--KbaR0\",\"emailValidationError\":\"EmailTabContent--email-validation-error--KbaR0\",\"spinner\":\"EmailTabContent--spinner--7dkIg\",\"label\":\"EmailTabContent--label--VrcIr\",\"textarea\":\"EmailTabContent--textarea--1h97A\",\"error-border\":\"EmailTabContent--error-border--b31sY\",\"errorBorder\":\"EmailTabContent--error-border--b31sY\",\"send-button\":\"EmailTabContent--send-button--R4a2H\",\"sendButton\":\"EmailTabContent--send-button--R4a2H\"};","// extracted by mini-css-extract-plugin\nexport default {\"headline\":\"LinkGoogleAccount--headline--HvrbG\",\"content\":\"LinkGoogleAccount--content--wzkX7\",\"gmail-icon\":\"LinkGoogleAccount--gmail-icon--ith9g\",\"gmailIcon\":\"LinkGoogleAccount--gmail-icon--ith9g\",\"btn-label\":\"LinkGoogleAccount--btn-label--B5Uw8\",\"btnLabel\":\"LinkGoogleAccount--btn-label--B5Uw8\",\"gmail-button\":\"LinkGoogleAccount--gmail-button--u3CEQ\",\"gmailButton\":\"LinkGoogleAccount--gmail-button--u3CEQ\",\"active\":\"LinkGoogleAccount--active--EQMr3\",\"focus\":\"LinkGoogleAccount--focus--mpuxT\"};","import React from 'react';\nimport PropTypes from 'prop-types';\nimport styles from './LinkGoogleAccount.scss';\n\nimport { t } from '../../../../../../utils/invite-friends-utils';\nimport { useInviteFriendsContext } from '../../../../../../state/InviteFriendsContext';\nimport { CLEAR_ALERT } from '../../../../../../state/InviteFriends.actions';\n\nconst LinkGoogleAccount = ({ requestContacts }) => {\n const { dispatch, track } = useInviteFriendsContext();\n\n const handleOnClick = () => {\n track({\n element: 'add_gmail_contacts',\n action: 'click',\n properties: { current_tab: 'email' }\n });\n dispatch({ type: CLEAR_ALERT });\n requestContacts();\n };\n return (\n <>\n

\n {t('modal.email.gmail_request.title')}\n

\n
\n

{t('modal.email.gmail_request.message')}

\n

\n {t('modal.email.gmail_request.disclaimer')}\n

\n
\n \n
\n \n {t('modal.email.gmail_request.button')}\n \n \n \n );\n};\n\nLinkGoogleAccount.propTypes = {\n requestContacts: PropTypes.func.isRequired\n};\n\nexport default LinkGoogleAccount;\n","// extracted by mini-css-extract-plugin\nexport default {\"headline\":\"GmailContactList--headline--wIxQ3\",\"disconnect-btn\":\"GmailContactList--disconnect-btn--ce6fi\",\"disconnectBtn\":\"GmailContactList--disconnect-btn--ce6fi\",\"search-input\":\"GmailContactList--search-input--pwQ4B\",\"searchInput\":\"GmailContactList--search-input--pwQ4B\",\"contact-list\":\"GmailContactList--contact-list--W2QgU\",\"contactList\":\"GmailContactList--contact-list--W2QgU\",\"fadeIn\":\"GmailContactList--fadeIn--ZgZO1\",\"spinner\":\"GmailContactList--spinner--Et4+N\",\"no-results\":\"GmailContactList--no-results--N3Xpe\",\"noResults\":\"GmailContactList--no-results--N3Xpe\",\"newKudo\":\"GmailContactList--newKudo--Hritm\",\"enterFadeOut\":\"GmailContactList--enterFadeOut--jZgsD\"};","// extracted by mini-css-extract-plugin\nexport default {\"athlete-metadata\":\"components--athlete-metadata--L1G69\",\"athleteMetadata\":\"components--athlete-metadata--L1G69\",\"name-and-email\":\"components--name-and-email--9n4AE\",\"nameAndEmail\":\"components--name-and-email--9n4AE\",\"name\":\"components--name--Bot7S\",\"disabled\":\"components--disabled--Pikmj\",\"email\":\"components--email--L8Vc8\",\"action-btn\":\"components--action-btn--ln6CC\",\"actionBtn\":\"components--action-btn--ln6CC\"};","import { compact, isEmpty, isNil, split, toLower, trim } from 'lodash-es';\n\n/**\n * Extracts the primary entry from an entries with multiple values.\n * If it cant be determined what the primary entry is, the first entry\n * in the list will be picked.\n *\n * entry example -\n * [ { displayName: 'Athlete Name_1', metadata: { primary: false } },\n * { displayName: 'Athlete Name_2', metadata: { primary: true } } ]\n *\n * @param {Object} entries - a list of entries with metadata that include a boolean which indicates\n * whether an entry is primary or not.\n * @returns\n */\nconst getPrimaryEntry = (entries) => {\n if (isNil(entries)) {\n return null;\n }\n const primary = entries.find((entry) => {\n const { metadata } = entry;\n return metadata ? metadata.primary : false;\n });\n return isEmpty(primary) ? entries[0] : primary;\n};\n\nexport const processContactsForUI = (contacts) => {\n const processedContacts = contacts.map((c, index) => {\n const { names, emailAddresses, photos } = c;\n\n const displayContact = {\n key: index,\n isOnStrava: false\n };\n // email address (required)\n if (isNil(getPrimaryEntry(emailAddresses))) {\n return null;\n }\n displayContact.email = getPrimaryEntry(emailAddresses).value;\n\n // display name (optional)\n if (isEmpty(names)) {\n displayContact.name = '';\n } else {\n displayContact.name = getPrimaryEntry(names).displayName;\n }\n // avatar picture (optional)\n if (isEmpty(photos)) {\n displayContact.picture = ''; // @strava/ui/Avatar requires blank string (vs null)\n } else {\n displayContact.picture = getPrimaryEntry(photos).url;\n }\n\n return displayContact;\n });\n return compact(processedContacts);\n};\n\nexport const extractEmailsFromString = (emails) => {\n return compact(split(toLower(emails), ',').map((email) => trim(email)));\n};\n\nexport default { processContactsForUI, extractEmailsFromString };\n","import React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport Button from '@strava/ui/Button';\n\nimport { isEmpty } from 'lodash-es';\nimport Avatar from '@strava/ui/Avatar';\nimport clsx from '@strava/ui/clsx';\nimport {\n FOLLOW_ACTIONS,\n FOLLOWING_STATUS\n} from 'constants/follows/following-constants';\nimport { followAthlete } from 'api/athlete';\nimport styles from './ContactEntry.scss';\nimport { t } from '../../../../../../../utils/invite-friends-utils';\nimport { useInviteFriendsContext } from '../../../../../../../state/InviteFriendsContext';\nimport {\n UPDATE_EMAILS,\n ADD_ALERT,\n CLEAR_ALERT\n} from '../../../../../../../state/InviteFriends.actions';\nimport { extractEmailsFromString } from '../../../EmailTabContent.utils';\n\nconst ContactEntry = ({ contact }) => {\n const [config, setConfig] = useState({\n action: FOLLOW_ACTIONS.add,\n disabled: false\n });\n const [currentFollowingStatus, setCurrentFollowingStatus] = useState(\n contact.followingStatus\n );\n\n const [isLoading, setIsLoading] = useState(false);\n\n const { state, dispatch, track } = useInviteFriendsContext();\n const { emails, currentAthlete, invitedEmailsList } = state;\n\n useEffect(() => {\n let action;\n let disabled = false;\n if (contact.isOnStrava) {\n if (currentFollowingStatus === FOLLOWING_STATUS.pending) {\n action = FOLLOW_ACTIONS.followRequested;\n disabled = true;\n } else if (currentFollowingStatus === FOLLOWING_STATUS.following) {\n action = FOLLOW_ACTIONS.following;\n disabled = true;\n } else {\n action = contact.approveFollowers\n ? FOLLOW_ACTIONS.requestToFollow\n : FOLLOW_ACTIONS.follow;\n }\n } else {\n action = FOLLOW_ACTIONS.add;\n const { email } = contact;\n disabled =\n invitedEmailsList.includes(email) ||\n extractEmailsFromString(emails).includes(email);\n }\n setConfig((prev) => {\n return { ...prev, action, disabled };\n });\n }, [\n contact,\n contact.approveFollowers,\n contact.email,\n contact.isOnStrava,\n currentFollowingStatus,\n emails,\n invitedEmailsList\n ]);\n\n const disabledTextStyle = config.disabled ? styles.disabled : '';\n\n const handleBtnClick = (action) => {\n dispatch({ type: CLEAR_ALERT });\n track({\n element: `${action}_btn`,\n action: 'click',\n properties: {\n current_tab: 'email',\n athlete_id: contact.id\n }\n });\n\n switch (action) {\n case FOLLOW_ACTIONS.add: {\n const separator = isEmpty(emails) ? '' : ',';\n dispatch({\n type: UPDATE_EMAILS,\n payload: { emails: emails.concat(separator, contact.email) }\n });\n setConfig((prev) => {\n return { ...prev, disabled: true };\n });\n break;\n }\n\n case FOLLOW_ACTIONS.follow:\n case FOLLOW_ACTIONS.requestToFollow: {\n setIsLoading(true);\n followAthlete({\n followerId: currentAthlete.id,\n followingId: contact.id\n })\n .then((status) => {\n if (status === FOLLOWING_STATUS.error) {\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: {\n severity: 'error',\n message: t(`modal.errors.generic`)\n }\n }\n });\n } else {\n setCurrentFollowingStatus(status);\n }\n })\n .finally(() => {\n setIsLoading(false);\n });\n break;\n }\n default: // noop\n }\n };\n\n return (\n <>\n
\n \n
\n

\n {contact.name}\n

\n

\n {contact.email}\n

\n
\n
\n handleBtnClick(config.action)}\n disabled={config.disabled || isLoading}\n >\n {t(`modal.email.gmail_authorized.contact_cta.${config.action}`)}\n \n \n );\n};\n\nContactEntry.propTypes = {\n contact: PropTypes.shape({\n id: PropTypes.number,\n name: PropTypes.string,\n picture: PropTypes.string,\n badge: PropTypes.string,\n email: PropTypes.string.isRequired,\n isOnStrava: PropTypes.bool.isRequired,\n followingStatus: PropTypes.oneOf([\n 'following',\n 'pending',\n 'can_follow',\n 'can_request'\n ]),\n approveFollowers: PropTypes.bool\n }).isRequired\n};\n\nexport default ContactEntry;\n","import React, { useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport Button from '@strava/ui/Button';\nimport { isEmpty, size } from 'lodash-es';\nimport Spinner from '@strava/ui/Spinner';\nimport styles from './GmailContactList.scss';\n\nimport { t } from '../../../../../../utils/invite-friends-utils';\nimport ContactEntry from './components/ContactEntry';\nimport { useInviteFriendsContext } from '../../../../../../state/InviteFriendsContext';\nimport { CLEAR_ALERT } from '../../../../../../state/InviteFriends.actions';\n\nconst GmailContactList = ({ contacts, disconnect, isLoading }) => {\n const [searchKeyword, setSearchKeyword] = useState(''); // value entered in the search field\n const [filterResults, setFilterResults] = useState(contacts);\n\n const { dispatch, track } = useInviteFriendsContext();\n\n // keeps track if its the initial search results (with no filter applied).\n // This is necessary because filtered results change based on the search box input\n // and we dont want to re-register a screen-enter at that point.\n const initialResults = useRef(true);\n\n useEffect(() => {\n if (!isLoading && initialResults.current) {\n track({\n element: 'google_contacts_feed',\n action: 'screen_enter',\n properties: {\n current_tab: 'email',\n contacts_count: filterResults.length,\n already_on_strava_count: size(\n filterResults.filter((contact) => contact.isOnStrava)\n )\n }\n });\n initialResults.current = false;\n }\n }, [isLoading, filterResults, track]);\n\n useEffect(() => {\n setFilterResults(contacts);\n }, [contacts]);\n\n const filterContacts = (e) => {\n dispatch({\n type: CLEAR_ALERT\n });\n\n const keyword = e.target.value;\n if (keyword !== '') {\n const results = contacts.filter((contact) => {\n return (\n contact.name.toLowerCase().includes(keyword.toLowerCase()) ||\n contact.email.toLowerCase().includes(keyword.toLowerCase())\n );\n });\n setFilterResults(results);\n } else {\n setFilterResults(contacts); // show all contacts\n }\n setSearchKeyword(keyword);\n };\n\n const handleOnDisconnect = () => {\n track({\n element: 'disconnect_gmail_contacts',\n action: 'click',\n properties: { current_tab: 'email' }\n });\n dispatch({ type: CLEAR_ALERT });\n disconnect();\n };\n\n return (\n <>\n

\n {t('modal.email.gmail_authorized.title')}\n

\n \n {t('modal.email.gmail_authorized.disconnect')}\n \n\n \n\n \n \n );\n};\n\nconst ResultsFeed = ({ isLoading, results }) => {\n if (isLoading) {\n return (\n
\n \n
\n );\n }\n if (results && results.length > 0) {\n return (\n
    \n {results.map((contact) => (\n
  • \n \n
  • \n ))}\n
\n );\n }\n return (\n

\n {t('modal.email.gmail_authorized.no_results_found')}\n

\n );\n};\n\nResultsFeed.propTypes = {\n isLoading: PropTypes.bool.isRequired,\n results: PropTypes.arrayOf(PropTypes.shape({})).isRequired\n};\n\nGmailContactList.propTypes = {\n contacts: PropTypes.arrayOf(PropTypes.shape({})).isRequired,\n disconnect: PropTypes.func.isRequired,\n isLoading: PropTypes.bool.isRequired\n};\n\nexport default GmailContactList;\n","import React, { useEffect, useRef, useCallback } from 'react';\nimport Button from '@strava/ui/Button';\nimport useGoogle from 'hooks/externalSocialPartners/useGoogle';\nimport Spinner from '@strava/ui/Spinner';\nimport { AuthorizationStatus } from 'hooks/externalSocialPartners/constants/auth-status-constants';\nimport {\n remove,\n uniqBy,\n isEmpty,\n find,\n isNil,\n escape,\n toLower,\n orderBy\n} from 'lodash-es';\nimport createNetworkingClient from 'utils/networking-client';\nimport * as EmailValidator from 'email-validator';\nimport clsx from '@strava/ui/clsx';\nimport { timeout } from 'utils/generalUtils';\nimport StravaAlert from 'components/StravaAlert';\nimport { Markup } from 'interweave';\nimport { FOLLOWING_STATUS } from 'constants/follows/following-constants';\nimport { useSafeState, useSafeDispatch } from '@strava/react-hooks';\nimport { useInviteFriendsContext } from '../../../../state/InviteFriendsContext';\n\nimport styles from './EmailTabContent.scss';\nimport LinkGoogleAccount from './components/LinkGoogleAccount';\n\nimport { t } from '../../../../utils/invite-friends-utils';\nimport GmailContactList from './components/GmailContactList/GmailContactList';\nimport {\n extractEmailsFromString,\n processContactsForUI\n} from './EmailTabContent.utils';\nimport {\n ADD_ALERT,\n CLEAR_ALERT,\n CLEAR_EMAILS,\n UPDATE_EMAILS,\n UPDATE_INVITED_EMAILS_LIST\n} from '../../../../state/InviteFriends.actions';\nimport { logError } from '../../../../../../../utils/sentry';\n\nconst EmailTabContent = () => {\n const { state, dispatch, track } = useInviteFriendsContext();\n const safeDispatch = useSafeDispatch(dispatch);\n\n const { currentAthlete, googleClientId, mocked, emails, alert } = state;\n\n const {\n authorizationStatus,\n contacts,\n requestContacts,\n disconnect\n } = useGoogle({\n clientId: googleClientId,\n mocked\n });\n\n const [processedContacts, setProcessedContacts] = useSafeState([]);\n const [isProcessingContacts, setIsProcessingContacts] = useSafeState(true);\n const [isSendingEmails, setIsSendingEmails] = useSafeState(false);\n\n const emailInputRef = useRef(null);\n\n const emailMessage = t('modal.email.message');\n\n const dispatchAlert = useSafeDispatch(\n useCallback(\n ({ severity, message, target }) => {\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: {\n severity,\n message,\n target\n }\n }\n });\n },\n [dispatch]\n )\n );\n\n useEffect(() => {\n if (authorizationStatus === AuthorizationStatus.UNAUTHORIZED) {\n dispatchAlert({\n severity: 'warning',\n message: t('modal.email.unauthorized')\n });\n } else if (authorizationStatus === AuthorizationStatus.DATA_FETCHED) {\n // extract primary entries for each contact and remove entries without email addresses\n let results = processContactsForUI(contacts);\n // eliminate duplicates\n results = uniqBy(results, 'email');\n // remove logged-in athlete from the results\n remove(results, (c) => c.email === currentAthlete.email);\n\n if (isEmpty(results)) {\n setIsProcessingContacts(false);\n } else {\n const importedEmails = results.map((c) => c.email);\n\n // find friends who are already on strava and update their entries with strava data\n createNetworkingClient()\n .post('/athletes/email_contacts_on_strava', {\n emails: importedEmails\n })\n .then((response) => {\n if (response && response.status === 200) {\n const { data: friendsAlreadyOnStrava } = response;\n friendsAlreadyOnStrava.forEach((friend) => {\n const contact = find(\n results,\n (c) => toLower(c.email) === toLower(friend.email)\n );\n if (!isNil(contact)) {\n contact.isOnStrava = true;\n contact.id = friend.id;\n contact.picture = friend.picture;\n contact.approveFollowers = friend.approve_followers;\n contact.followingStatus = friend.following_status;\n contact.name = friend.display_name;\n contact.badge = friend.badge;\n }\n });\n } else {\n dispatchAlert({\n severity: 'error',\n message: t(`modal.errors.generic`)\n });\n }\n results = orderBy(\n results,\n [\n (contact) =>\n [\n FOLLOWING_STATUS.canFollow,\n FOLLOWING_STATUS.canRequest\n ].includes(contact.followingStatus), // 1st - followable athletes\n (contact) => contact.isOnStrava, // 2nd - all other strava athletes\n (contact) => isNil(contact.name) || contact.name === '', // 3rd - google contacts with display name\n (contact) => contact.name // 4th - the rest, order all groups by display name\n ],\n ['desc', 'desc', 'asc', 'asc']\n );\n\n setProcessedContacts(results);\n })\n .catch(() => {\n dispatchAlert({\n severity: 'error',\n message: t(`modal.errors.generic`)\n });\n })\n .finally(() => {\n setIsProcessingContacts(false);\n });\n }\n }\n }, [\n authorizationStatus,\n contacts,\n currentAthlete.email,\n dispatchAlert,\n setIsProcessingContacts,\n setProcessedContacts\n ]);\n\n useEffect(() => {\n if (emailInputRef.current) {\n emailInputRef.current.focus();\n }\n }, [emailInputRef]);\n\n // show error message to athlete when something goes wrong during authorization\n useEffect(() => {\n if (authorizationStatus === AuthorizationStatus.ERROR) {\n dispatchAlert({ severity: 'error', message: t(`modal.errors.generic`) });\n }\n }, [authorizationStatus, dispatchAlert]);\n\n const alreadyOnStravaMessage = (alreadyOnStrava) => {\n let message;\n const numOnStrava = alreadyOnStrava.length;\n\n if (numOnStrava === 1) {\n message = t('modal.email.already_on_strava', {\n email_address: escape(alreadyOnStrava[0])\n });\n } else if (numOnStrava === 2) {\n message = t('modal.email.x_and_y_already', {\n email_address: escape(alreadyOnStrava[0]),\n other_email_address: escape(alreadyOnStrava[1])\n });\n } else {\n message = t('modal.email.x_and_y_and_other_already', {\n email_address: escape(alreadyOnStrava[0]),\n other_email_address: escape(alreadyOnStrava[1]),\n count: numOnStrava - 2\n });\n }\n return message;\n };\n\n const isValidEmailList = (emailList) => {\n return isNil(emailList.find((email) => !EmailValidator.validate(email)));\n };\n\n const handleFormSubmission = async (event) => {\n event.preventDefault();\n\n dispatch({ type: CLEAR_ALERT });\n const emailList = extractEmailsFromString(emails);\n\n track({\n action: 'click',\n element: 'send_email',\n properties: {\n current_tab: 'email',\n email_count: emailList.length,\n is_valid_email_list: isValidEmailList(emailList),\n emails: emailList.toString()\n }\n });\n\n // validate emails\n for (let i = 0; i < emailList.length; i++) {\n if (!EmailValidator.validate(emailList[i])) {\n dispatchAlert({\n severity: 'error',\n message: t(`modal.errors.invalid_email`),\n target: 'email-input'\n });\n emailInputRef.current.focus();\n return;\n }\n }\n\n setIsSendingEmails(true);\n createNetworkingClient()\n .post(`/invites`, {\n to: emailList,\n body: emailMessage,\n invite_dialog: true\n })\n .then(async (response) => {\n if (response.status === 200) {\n const { sent, not_sent: notSent } = response.data;\n if (!isEmpty(sent)) {\n dispatchAlert({\n severity: 'success',\n message: t('modal.email.sent')\n });\n dispatch({\n type: UPDATE_INVITED_EMAILS_LIST,\n payload: sent\n });\n dispatch({ type: CLEAR_EMAILS });\n\n // `emails sent` message auto-clears after 4 seconds\n await timeout(4000);\n\n safeDispatch({ type: CLEAR_ALERT });\n }\n if (!isEmpty(notSent)) {\n const { already_on_strava: alreadyOnStrava } = notSent;\n if (!isEmpty(alreadyOnStrava)) {\n dispatchAlert({\n severity: 'warning',\n message: (\n \n )\n });\n }\n }\n } else {\n logError(response.error);\n dispatchAlert({\n severity: 'error',\n message: t('modal.errors.generic')\n });\n }\n })\n .catch((e) => {\n logError(e);\n dispatchAlert({\n severity: 'error',\n message: t('modal.errors.generic')\n });\n })\n .finally(() => {\n setIsSendingEmails(false);\n });\n };\n\n const handleInputChange = (event) => {\n dispatch({ type: CLEAR_ALERT });\n dispatch({ type: UPDATE_EMAILS, payload: { emails: event.target.value } });\n };\n\n return (\n <>\n {!isEmpty(alert) && (\n {alert.message}\n )}\n
\n
\n

{t('modal.email.subtitle')}

\n
\n \n \n\n \n \n\n \n {isSendingEmails\n ? t('modal.email.sending')\n : t('modal.email.send')}\n \n \n
\n
\n {[\n AuthorizationStatus.AUTHORIZED,\n AuthorizationStatus.DATA_FETCHED\n ].includes(authorizationStatus) && (\n \n )}\n {[\n AuthorizationStatus.READY,\n AuthorizationStatus.ERROR,\n AuthorizationStatus.UNAUTHORIZED\n ].includes(authorizationStatus) && (\n \n )}\n {authorizationStatus === AuthorizationStatus.INITIATED && (\n
\n \n
\n )}\n
\n
\n \n );\n};\n\nexport default EmailTabContent;\n","import React, { useEffect } from 'react';\n\nimport ModalWithTabs, {\n ModalTabs,\n ModalTabList,\n ModalTab,\n ModalTabPanels,\n ModalTabPanel\n} from '@strava/ui/ModalWithTabs';\nimport { t } from '../../utils/invite-friends-utils';\nimport styles from './InviteFriendsModal.scss';\nimport { useInviteFriendsContext } from '../../state/InviteFriendsContext';\nimport {\n CLEAR_ALERT,\n CHANGE_TAB,\n CLOSE_MODAL\n} from '../../state/InviteFriends.actions';\nimport EmailTabContent from './components/EmailTabContent/EmailTabContent';\nimport FindFacebookFriends from '../../../friends/FindFacebookFriends';\nimport { INVITE_FRIENDS } from '../../../friends/utils/friendsConstants';\n\nconst InviteFriendsModal = () => {\n const { state, dispatch, track } = useInviteFriendsContext();\n const {\n isModalOpen,\n modalTabIndex,\n currentAthlete,\n fbAppId,\n fbVersion,\n locale\n } = state;\n\n useEffect(() => {\n track({\n action: 'screen_enter'\n });\n }, [track]);\n\n const handleTabsChange = (selectedTab) => {\n dispatch({ type: CHANGE_TAB, payload: { modalTabIndex: selectedTab } });\n dispatch({ type: CLEAR_ALERT });\n track({\n element: selectedTab === 0 ? 'email' : 'facebook',\n action: 'click'\n });\n };\n\n return (\n dispatch({ type: CLOSE_MODAL })}\n title={t('modal.title')}\n aria-label={t('modal.aria-label')}\n data-cy=\"invite-friends-modal\"\n >\n \n \n {t('modal.email.title')}\n {t('modal.facebook.title')}\n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default InviteFriendsModal;\n","import {\n ADD_ALERT,\n CHANGE_TAB,\n CLEAR_ALERT,\n CLEAR_EMAILS,\n CLOSE_MODAL,\n OPEN_MODAL,\n UPDATE_EMAILS,\n UPDATE_FB_FRIENDS,\n UPDATE_FB_FRIEND_FOLLOWING_STATUS,\n UPDATE_INVITED_EMAILS_LIST\n} from './InviteFriends.actions';\n\nexport function reducer(state, action) {\n switch (action.type) {\n case CLOSE_MODAL: {\n return { ...state, isModalOpen: false };\n }\n case OPEN_MODAL: {\n return { ...state, isModalOpen: true };\n }\n case UPDATE_EMAILS: {\n const { emails } = action.payload;\n return {\n ...state,\n emails\n };\n }\n\n case UPDATE_INVITED_EMAILS_LIST: {\n return {\n ...state,\n invitedEmailsList: [...state.invitedEmailsList, ...action.payload]\n };\n }\n\n case UPDATE_FB_FRIENDS: {\n const { fbFriends } = action.payload;\n return {\n ...state,\n fbFriends\n };\n }\n case UPDATE_FB_FRIEND_FOLLOWING_STATUS: {\n const { id, isFollowable, followingStatus } = action.payload;\n const friend = state.fbFriends[id];\n return {\n ...state,\n fbFriends: {\n ...state.fbFriends,\n [id]: { ...friend, isFollowable, followingStatus }\n }\n };\n }\n case ADD_ALERT: {\n const { alert } = action.payload;\n return {\n ...state,\n alert\n };\n }\n case CLEAR_ALERT: {\n return {\n ...state,\n alert: {}\n };\n }\n case CHANGE_TAB: {\n const { modalTabIndex } = action.payload;\n return { ...state, modalTabIndex };\n }\n case CLEAR_EMAILS: {\n return { ...state, emails: '' };\n }\n default: {\n throw new Error(`${action.type} - not recognized`);\n }\n }\n}\n\nexport default { reducer };\n","import React, { useCallback, useEffect, useMemo, useReducer } from 'react';\nimport PropTypes from 'prop-types';\n\nimport Button from '@strava/ui/Button';\nimport cx from '@strava/ui/clsx';\nimport { camelCase } from 'lodash-es';\nimport FacebookLogo from '@strava/icons/LogosFacebookXsmall';\nimport { trackV2 } from 'utils/analytics';\nimport { useInView } from 'react-intersection-observer';\nimport styles from './InviteFriendsButton.scss';\nimport { t } from '../../utils/invite-friends-utils';\nimport InviteFriendsModal from '../InviteFriendsModal/InviteFriendsModal';\nimport InviteFriendsContext from '../../state/InviteFriendsContext';\nimport { reducer } from '../../state/InviteFriends.reducer';\nimport { OPEN_MODAL } from '../../state/InviteFriends.actions';\n\nconst InviteFriendsButton = ({\n source,\n googleClientId,\n currentAthlete,\n locale,\n fbAppId,\n fbVersion,\n mocked,\n defaultTabIndex\n}) => {\n const [intersectionObserverRef, inView] = useInView({\n threshold: 1\n });\n\n const track = useCallback(\n (fields) => {\n trackV2({\n page: 'find_and_invite',\n category: 'connections',\n ...fields,\n properties: {\n source,\n default_tab: defaultTabIndex === 0 ? 'email' : 'facebook',\n ...fields.properties\n }\n });\n },\n [defaultTabIndex, source]\n );\n\n const [state, dispatch] = useReducer(reducer, {\n isModalOpen: false,\n googleClientId,\n currentAthlete,\n locale,\n fbAppId,\n fbVersion,\n fbFriends: {},\n invitedEmailsList: [],\n mocked,\n emails: '',\n alert: {},\n modalTabIndex: defaultTabIndex\n });\n\n const providerState = useMemo(\n () => ({\n state,\n dispatch,\n track\n }),\n [state, track]\n );\n\n const element = 'invite_friends_btn';\n\n useEffect(() => {\n if (inView) {\n track({ page: source, element, action: 'screen_enter' });\n }\n }, [inView, source, track]);\n\n const config = (() => {\n let cta = t('cta.find_and_invite_friends');\n let variant = 'text';\n let logo = null;\n\n if (source === 'onboarding') {\n variant = 'primary';\n cta = t('cta.connect_with_facebook');\n logo = ;\n } else if (\n [\n 'athlete_search',\n 'follows_following',\n 'follows_suggested',\n 'follows_followers',\n 'follows_blocked'\n ].includes(source)\n ) {\n variant = 'primary';\n } else if (source === 'header_menu') {\n cta = t('cta.find_friends');\n }\n return { cta, variant, logo };\n })();\n\n const handleButtonClick = () => {\n dispatch({ type: OPEN_MODAL });\n track({ page: source, element, action: 'click' }); // TODO confirm what page should be here\n };\n\n return (\n \n \n {config.logo}\n {config.cta}\n \n\n {state.isModalOpen && }\n \n );\n};\n\nInviteFriendsButton.defaultProps = {\n mocked: false,\n defaultTabIndex: 0 // defaults to first tab (email)\n};\n\nInviteFriendsButton.propTypes = {\n source: PropTypes.oneOf([\n 'athlete_search',\n 'dashboard_sidebar',\n 'follows_blocked',\n 'follows_followers',\n 'follows_following',\n 'follows_suggested',\n 'header_menu',\n 'onboarding' // facebook button on onboarding dashboard feed\n ]).isRequired,\n googleClientId: PropTypes.string.isRequired,\n mocked: PropTypes.bool,\n fbAppId: PropTypes.number.isRequired,\n fbVersion: PropTypes.string.isRequired,\n locale: PropTypes.string.isRequired,\n currentAthlete: PropTypes.shape({\n email: PropTypes.string.isRequired,\n id: PropTypes.number.isRequired\n }).isRequired,\n defaultTabIndex: PropTypes.oneOf([0, 1]) // 0 - email, 1 - FB\n};\n\nexport default InviteFriendsButton;\n","// extracted by mini-css-extract-plugin\nexport default {\"modal-open\":\"Modal--modal-open--kChhd\",\"modalOpen\":\"Modal--modal-open--kChhd\",\"base\":\"Modal--base--3VnHO\",\"fade-in\":\"Modal--fade-in--6nkdi\",\"fadeIn\":\"Modal--fade-in--6nkdi\",\"fade-out\":\"Modal--fade-out--puMJg\",\"fadeOut\":\"Modal--fade-out--puMJg\",\"dialog\":\"Modal--dialog--+VJZV\",\"content\":\"Modal--content--PBv25\"};","import React from 'react';\nimport ReactModal from 'react-modal';\nimport PropTypes from 'prop-types';\n\nimport styles from './styles.scss';\n\nconst customStyles = {\n overlay: {\n zIndex: '100'\n },\n afterOpen: '',\n beforeClose: ''\n};\n\nconst Modal = (props) => (\n \n
{props.children}
\n \n);\n\nModal.propTypes = {\n children: PropTypes.node.isRequired,\n isOpen: PropTypes.bool.isRequired,\n onRequestClose: PropTypes.func.isRequired,\n ariaHideApp: PropTypes.bool,\n shouldCloseOnOverlayClick: PropTypes.bool,\n className: PropTypes.string,\n dialogClassName: PropTypes.string,\n onAfterOpen: PropTypes.func\n};\n\nModal.defaultProps = {\n ariaHideApp: false,\n shouldCloseOnOverlayClick: true,\n className: '',\n dialogClassName: '',\n onAfterOpen: null\n};\n\nexport default Modal;\n","import { useEffect, useState } from 'react';\nimport createNetworkingClient from 'utils/networking-client';\nimport { injectFacebookScript } from 'externalSocialPartners';\nimport { difference, isEmpty, split } from 'lodash-es';\nimport { isDev, timeout } from 'utils/devUtils';\nimport { FOLLOWING_STATUS } from 'constants/follows/following-constants';\nimport { AuthorizationStatus } from './constants/auth-status-constants';\nimport { logError } from '../../utils/sentry';\n\n/**\n * Permissions required by FB graph endpoints - see https://developers.facebook.com/docs/permissions/reference/\n */\nconst Permissions = Object.freeze({\n FRIEND_LIST: ['user_friends']\n});\n\n/**\n *\n * Requests for user permissions before attempting to interact with Facebook Graph API.\n * eg. athletes can request for their friends which will prompt them to give strava the right permissions\n * if the permissions are missing.\n *\n * DEVELOPMENT NOTE: The FB api doesn't work locally, so we get around it with local data, while still\n * preserving the flow as much as possible\n *\n * @param {Object} arg\n * @param {number} arg.appId - Strava app client id which changes based on the environment (dev, staging and prod).\n * @param {string} arg.version - Facebook graph version.\n * @param {string} arg.locale - current athlete's locale\n * @param {boolean} arg.autoSync - whether to auto sync and try to pull FB friends before athlete clicks connect FB btn\n * (optional, defaults to true)\n * @param {string} arg.source - the page/component calling the hook\n * @returns {Object} response\n * @returns {boolean} response.ready - Whether FB javascript has been injected in the document.\n * @returns {string} response.authorizationStatus - enum value representing an athletes FB authorization state.\n * @returns {string} response.friends - Populated with a list of FB friends when requested by athlete.\n */\nconst useFacebook = ({ appId, version, locale, autoSync = true, source }) => {\n const [authorizationStatus, setAuthorizationStatus] = useState(\n AuthorizationStatus.INITIATED\n );\n const [fbFriends, setFbFriends] = useState([]);\n\n /**\n * If autoSync is on, during the first request to retrieve data from FB graph, we check if the athlete is already\n * connected to FB and if they have granted the right permissions for strava to retrieve\n * the requested data from their account without showing any FB verification/prompt UI.\n */\n const [isInitialRequest, setIsInitialRequest] = useState(true);\n\n /**\n * Inject FB graph api JS.\n *\n * Note - We need to do this for components that are mounted in haml templates since we are not\n * guaranteed that the script is available when the components attempt to request for FB graph data\n * on component mount.\n */\n useEffect(() => {\n injectFacebookScript({\n appId,\n version,\n locale,\n callback: () => setAuthorizationStatus(AuthorizationStatus.READY)\n });\n }, [appId, locale, version]);\n\n /**\n * If autoSync is off, we need to request permissions before we can proceed with logging in\n * and requesting friends\n */\n useEffect(() => {\n if (authorizationStatus === AuthorizationStatus.READY && !autoSync) {\n setAuthorizationStatus(AuthorizationStatus.REQUEST_PERMISSIONS);\n }\n }, [authorizationStatus, autoSync]);\n\n /**\n *\n * Checks to see if all the requested scopes were granted by the athlete.\n *\n * @param {Object} arg\n * @param {string} arg.grantedScopes - list of scopes that have been granted by the athlete\n * @param {string} arg.requestedScopes - list of scopes that are required by fb graph in order for strava\n * to retrieve requested user information.\n * @returns {boolean} - boolean value indicating whether the connected account has\n * all the required permissions or not.\n */\n const checkPermissions = ({ grantedScopes, requestedScopes }) => {\n if (isEmpty(grantedScopes)) {\n return false;\n }\n return difference(requestedScopes, grantedScopes).length === 0;\n };\n\n /**\n * FB graph `permissions` endpoint returns permissions in the following format\n * [{\n * \"permission\": \"user_friends\",\n * \"status\": \"granted\"\n * }, {...}, ...]\n * See - https://developers.facebook.com/docs/facebook-login/web/permissions/\n *\n * Retrieves only granted permissions and process them into an array - eg. ['user_friends', ... ]\n * which is then used by #checkPermissions in #stravaFbProxyPostPermissions\n *\n * @param {Array} data - the data from the `permissions` endpoint response\n */\n const getGrantedScopes = (data) => {\n return data.filter((p) => p.status === 'granted').map((p) => p.permission);\n };\n\n /**\n * Uses `active` as a proxy to check if the given token has all the permissions\n * that are requested.\n *\n * @param {Object} arg\n * @param {string} arg.accessToken - token for connected FB account\n * @param {Array} arg.requestedScopes - List of permissions required for the requested data to be retrieved\n * form FB graph\n * @returns {Promise} - boolean value indicating whether the connected account has\n * all the required permissions or not.\n */\n const stravaFbProxyPostPermissions = ({ accessToken, requestedScopes }) => {\n if (isDev()) {\n return new Promise((resolve) => {\n // import mock permissions data dynamically\n import('./data/facebook_permissions_sample.json').then((module) => {\n resolve(\n checkPermissions({\n grantedScopes: getGrantedScopes(module.default),\n requestedScopes\n })\n );\n });\n });\n }\n return new Promise((resolve, reject) => {\n createNetworkingClient()\n .post('/facebook_open_graph_actions/permissions', {\n access_token: accessToken\n })\n .then((response) => {\n if (response && response.status === 200) {\n resolve(\n checkPermissions({\n grantedScopes: getGrantedScopes(response.data),\n requestedScopes\n })\n );\n } else {\n reject(response.error);\n }\n })\n .catch((e) => reject(e));\n });\n };\n\n /**\n * Uses `active` as a proxy to retrieve friends data from FB graph\n *\n * @param {Object} arg\n * @param {string} arg.accessToken - token for connected FB account\n * @returns {Promise} - List of friends for the connected FB account.\n */\n const stravaFbProxyPostFriends = ({ accessToken }) => {\n if (isDev()) {\n return new Promise((resolve) => {\n // import mock friend data dynamically\n import('./data/facebook_friends_sample.json').then(async (module) => {\n await timeout(5);\n resolve(module.default);\n });\n });\n }\n return new Promise((resolve, reject) => {\n createNetworkingClient()\n .post('/facebook_open_graph_actions/friends', {\n access_token: accessToken,\n source\n })\n .then((response) => {\n if (response && response.status === 200) {\n resolve(response.data);\n } else {\n reject(response.error);\n }\n })\n .catch((e) => {\n reject(e);\n });\n });\n };\n\n /**\n * Hits Strava endpoint to get the Strava athletes associated with FB user ids\n *\n * @param {Object} arg\n * @param {Array} arg.facebookUIDs - list of facebook UIDs\n * @returns {Promise} - list of FB friends as Strava athletes\n */\n const stravaUsersFromFbIds = ({ facebookUIDs }) => {\n return new Promise((resolve, reject) => {\n createNetworkingClient()\n .post('/athletes/facebook_friends_on_strava', {\n facebook_uids: facebookUIDs\n })\n .then((response) => {\n if (response && response.status === 200) {\n resolve(response.data);\n } else {\n reject(response.error);\n }\n })\n .catch((e) => {\n reject(e);\n });\n });\n };\n\n /**\n * Uses FB graph to prompt the user to log in with the given list of\n * permissions.\n *\n * @param {Array} requestedScopes - list of permissions that are required to retrieve requested data\n * @returns {Promise} -An object with the following attributes:\n * `hasPermissions` - a boolean indicating whether the athlete authorized all permissions\n * `accessToken` - token for the connected FB account\n */\n const fbGraphApiLogin = (requestedScopes) => {\n return new Promise((resolve) => {\n const options = { scope: requestedScopes, return_scopes: true };\n if (authorizationStatus === AuthorizationStatus.REQUEST_NEW_PERMISSIONS) {\n options.auth_type = 'rerequest';\n }\n window.FB.login((response) => {\n if (response.authResponse) {\n const { accessToken, grantedScopes } = response.authResponse;\n /**\n * grantedScopes is a comma-separated list of granted scopes eg.\n * `email, user_friends ...`\n *\n * The next step generates an array of permissions eg. eg. ['user_friends', ... ]\n * which is then used by #checkPermissions\n */\n const grantedScopesList = split(grantedScopes, ',');\n resolve({\n hasPermissions: checkPermissions({\n grantedScopes: grantedScopesList,\n requestedScopes\n }),\n accessToken\n });\n } else {\n resolve({ hasPermissions: false });\n }\n }, options);\n });\n };\n\n /**\n * Checks the permissions for an already logged-in athlete and request for new permissions if the permissions\n * are insufficient. A UI dialog is used to request for more permissions if necessary.\n *\n * @param {Array} requestedScopes - list of permissions that are required to retrieve requested data\n * @returns {Promise} -An object with the following attributes:\n * `status` - enum representing the authorization status (see auth-status-constants#AuthorizationStatus)\n * `accessToken` - token for the connected FB account\n * */\n const requestPermissions = (requestedScopes) => {\n return new Promise((resolve, reject) => {\n if (autoSync && isInitialRequest) {\n /**\n * The component that is requesting data from FB has been mounted on the page, before prompting the user to\n * provide permissions, we check if they have already provided the permissions. If they are connected\n * but do not have the required permissions, then we update the status to `RequestNewPermissions` (which can\n * be used by the UI to show `Login with FB` button)\n */\n window.FB.getLoginStatus((response) => {\n // see https://developers.facebook.com/docs/facebook-login/web/ for possible status types\n if (response.status === 'connected') {\n const { accessToken } = response.authResponse;\n stravaFbProxyPostPermissions({\n accessToken,\n requestedScopes\n })\n .then((hasPermissions) => {\n const status = hasPermissions\n ? AuthorizationStatus.AUTHORIZED\n : AuthorizationStatus.REQUEST_NEW_PERMISSIONS;\n resolve({ status, accessToken });\n })\n .catch((e) => {\n reject(e);\n });\n } else {\n resolve({ status: AuthorizationStatus.REQUEST_NEW_PERMISSIONS });\n }\n });\n setIsInitialRequest(false);\n } else {\n /**\n * At this point, it has been determined that either the connected account does not have sufficient permissions or\n * an account is not connected at all.\n * The athlete is presented with the FB login button which when clicked will open a dialog requesting for\n * the required permissions. If they do not provide all of the permissions, the status will be updated to Unauthorized.\n * */\n fbGraphApiLogin(requestedScopes).then(\n ({ hasPermissions, accessToken }) => {\n const status = hasPermissions\n ? AuthorizationStatus.AUTHORIZED\n : AuthorizationStatus.UNAUTHORIZED;\n resolve({ status, accessToken });\n }\n );\n }\n });\n };\n\n /**\n * Request for friends data from FB graph\n */\n const requestFriends = () => {\n setAuthorizationStatus(AuthorizationStatus.READY); // reset auth status before flow\n requestPermissions(Permissions.FRIEND_LIST)\n .then(({ status, accessToken }) => {\n setAuthorizationStatus(status); // possible values - Authorized, UnAuthorized and NewPermissions\n if (status === AuthorizationStatus.AUTHORIZED) {\n stravaFbProxyPostFriends({ accessToken })\n .then((fbData) => {\n if (fbData.length > 0) {\n // pull out FB uids and get Strava athletes associated with them\n const facebookUIDs = fbData.map((friend) => friend.id);\n stravaUsersFromFbIds({ facebookUIDs })\n .then((stravaData) => {\n const camelCaseFriends = stravaData.map((athlete) => {\n return {\n id: athlete.id,\n picture: athlete.picture,\n followingStatus: athlete.following_status,\n isFollowable:\n athlete.following_status ===\n FOLLOWING_STATUS.canFollow ||\n athlete.following_status ===\n FOLLOWING_STATUS.canRequest,\n approveFollowers: athlete.approve_followers,\n badge: athlete.badge,\n displayName: athlete.display_name,\n subtitle: athlete.display_location\n };\n });\n setFbFriends(camelCaseFriends);\n setAuthorizationStatus(AuthorizationStatus.DATA_FETCHED);\n })\n .catch((e) => {\n // something went wrong while retrieving or processing Strava athletes from FB data\n setAuthorizationStatus(AuthorizationStatus.ERROR);\n logError(e);\n });\n } else {\n // there were no FB uids to get Strava athletes from\n setFbFriends([]);\n setAuthorizationStatus(AuthorizationStatus.DATA_FETCHED);\n }\n })\n .catch((e) => {\n // something went wrong while retrieving or processing friend data\n setAuthorizationStatus(AuthorizationStatus.ERROR);\n logError(e);\n });\n }\n })\n .catch((e) => {\n // something went wrong while requesting or checking permissions\n setAuthorizationStatus(AuthorizationStatus.ERROR);\n logError(e);\n });\n };\n\n return {\n fbFriends,\n authorizationStatus,\n requestFriends\n };\n};\n\nexport default useFacebook;\n","// extracted by mini-css-extract-plugin\nexport default {\"facebook-button\":\"LinkFacebookButton--facebook-button--+5rmt\",\"facebookButton\":\"LinkFacebookButton--facebook-button--+5rmt\",\"full-width\":\"LinkFacebookButton--full-width--WXCxj\",\"fullWidth\":\"LinkFacebookButton--full-width--WXCxj\"};","import React from 'react';\nimport PropTypes from 'prop-types';\nimport Button from '@strava/ui/Button';\nimport clsx from '@strava/ui/clsx';\nimport LogosFacebookSmall from '@strava/icons/LogosFacebookSmall';\nimport styles from './LinkFacebookButton.scss';\n\nconst LinkFacebookButton = ({ children, onClick, fullWidth, className }) => (\n \n \n {children}\n \n);\n\nLinkFacebookButton.defaultProps = {\n className: null,\n fullWidth: false\n};\n\nLinkFacebookButton.propTypes = {\n onClick: PropTypes.func.isRequired,\n children: PropTypes.node.isRequired,\n className: PropTypes.string,\n fullWidth: PropTypes.bool\n};\n\nexport default LinkFacebookButton;\n","// extracted by mini-css-extract-plugin\nexport default {\"headline\":\"LinkFacebookAccount--headline--H3YIb\"};","import React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport { INVITE_FRIENDS } from '../../utils/friendsConstants';\nimport { t } from '../../utils/friendsUtils';\nimport { CLEAR_ALERT } from '../../state/friendsActions';\nimport { useFriendsContext } from '../../state/FriendsContext';\nimport LinkFacebookButton from '../shared/LinkFacebookButton';\n\nimport styles from './LinkFacebookAccount.scss';\n\n/* display connect with FB cta */\nconst LinkFacebookAccount = ({ requestFriends, authorizationStatus }) => {\n const { state, dispatch, track } = useFriendsContext();\n const { source } = state;\n const isInviteFriends = source === INVITE_FRIENDS;\n const analyticsBySource = isInviteFriends\n ? {\n element: 'connect_with_facebook',\n properties: { current_tab: 'facebook' }\n }\n : {\n element: 'connect_fb',\n properties: {}\n };\n\n useEffect(() => {\n track({\n ...analyticsBySource,\n action: 'screen_enter',\n properties: {\n ...analyticsBySource.properties,\n authorization_status: authorizationStatus\n }\n });\n }, [analyticsBySource, authorizationStatus, track]);\n\n const handleClick = () => {\n dispatch({ type: CLEAR_ALERT });\n track({\n ...analyticsBySource,\n action: 'click',\n properties: {\n ...analyticsBySource.properties\n }\n });\n requestFriends();\n };\n\n return (\n <>\n {isInviteFriends && (\n <>\n

{t('invite_friends.title')}

\n

{t('invite_friends.message')}

\n \n )}\n \n {isInviteFriends ? t('invite_friends.button') : t('onboarding.button')}\n \n \n );\n};\n\nLinkFacebookAccount.propTypes = {\n requestFriends: PropTypes.func.isRequired,\n authorizationStatus: PropTypes.string.isRequired\n};\n\nexport default LinkFacebookAccount;\n","// extracted by mini-css-extract-plugin\nexport default {\"fb-header\":\"InviteFriendsHeader--fb-header--EzGjF\",\"fbHeader\":\"InviteFriendsHeader--fb-header--EzGjF\",\"headline\":\"InviteFriendsHeader--headline--E93dU\"};","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport Button from '@strava/ui/Button';\nimport { bulkFollow } from 'api/athlete';\nimport { FOLLOWING_STATUS } from 'constants/follows/following-constants';\nimport { useFriendsContext } from '../../../state/FriendsContext';\nimport {\n CLEAR_ALERT,\n ADD_ALERT,\n UPDATE_FRIEND_FOLLOWING_STATUS\n} from '../../../state/friendsActions';\nimport { t } from '../../../utils/friendsUtils';\n\nimport styles from './InviteFriendsHeader.scss';\n\n/* invite friends version of the fb friends modal has header with `follow all` button */\nconst InviteFriendsHeader = ({ sortedFriends }) => {\n const { state, dispatch, track } = useFriendsContext();\n const [isProcessing, setIsProcessing] = useState(false);\n\n const handleFollowAll = async () => {\n setIsProcessing(true);\n dispatch({ type: CLEAR_ALERT });\n\n const followeeIds = sortedFriends\n .filter((friend) => friend.isFollowable)\n .map((friend) => friend.id);\n\n bulkFollow({ followeeIds })\n .then(({ success, followedAthleteIds }) => {\n if (success) {\n followedAthleteIds.forEach((id) => {\n const friend = state.friends[id];\n dispatch({\n type: UPDATE_FRIEND_FOLLOWING_STATUS,\n payload: {\n id: friend.id,\n isFollowable: false,\n followingStatus: friend.approveFollowers\n ? FOLLOWING_STATUS.pending\n : FOLLOWING_STATUS.following\n }\n });\n });\n } else {\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: { severity: 'error', message: t(`errors.generic`) }\n }\n });\n }\n track({\n element: 'follow_all_btn',\n action: 'click',\n properties: {\n current_tab: 'facebook',\n follow_all_count: followeeIds.length,\n follow_all_status: success ? 'success' : 'error'\n }\n });\n })\n .finally(() => setIsProcessing(false));\n };\n\n return (\n
\n

\n {t('invite_friends.friends_on_strava')}\n

\n {sortedFriends.length > 0 && (\n // follow all\n friend.isFollowable)\n }\n onClick={handleFollowAll}\n >\n {t('cta_actions.follow_all')}\n \n )}\n
\n );\n};\n\nInviteFriendsHeader.propTypes = {\n sortedFriends: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.number,\n picture: PropTypes.string,\n followingStatus: PropTypes.oneOf([\n FOLLOWING_STATUS.canFollow,\n FOLLOWING_STATUS.canRequest,\n FOLLOWING_STATUS.pending,\n FOLLOWING_STATUS.following\n ]),\n isFollowable: PropTypes.bool,\n approveFollowers: PropTypes.bool,\n badge: PropTypes.string,\n displayName: PropTypes.string,\n displayLocation: PropTypes.string\n })\n ).isRequired\n};\n\nexport default InviteFriendsHeader;\n","import React, { useEffect, useRef } from 'react';\nimport { sortBy } from 'lodash-es';\nimport { useFriendsContext } from '../../state/FriendsContext';\nimport { t } from '../../utils/friendsUtils';\nimport { INVITE_FRIENDS, ONBOARDING } from '../../utils/friendsConstants';\nimport InviteFriendsHeader from './InviteFriendsHeader';\nimport FriendList from '../shared/FriendList';\nimport FriendListItem from '../shared/FriendListItem';\n\n/* display list of friends with CTA to follow them */\nconst FacebookFriendList = () => {\n const { state, track } = useFriendsContext();\n const { friends, source } = state;\n const sortedFriends = sortBy(Object.values(friends), 'sortedIndex');\n const friendCount = sortedFriends.length;\n const onboardingFriendCountMessage = (() => {\n switch (friendCount) {\n case 0:\n return t('friend_list.no_fb_matches');\n case 1:\n return t('friend_list.one_friend_to_follow');\n default:\n return t('friend_list.more_friends_to_follow', {\n friend_count: friendCount\n });\n }\n })();\n\n // friends will change as friends get followed, so we\n // want to track the initial screen_enter\n const initialScreenEnter = useRef(true);\n useEffect(() => {\n if (initialScreenEnter.current) {\n const analytics = {\n element: 'facebook_friends_list',\n action: 'screen_enter',\n properties: {\n friends_count: friendCount\n }\n };\n if (source === INVITE_FRIENDS) {\n analytics.properties.current_tab = 'facebook';\n }\n track(analytics);\n initialScreenEnter.current = false;\n }\n }, [friendCount, source, track]);\n\n return (\n <>\n {source === INVITE_FRIENDS && (\n \n )}\n {source === ONBOARDING &&

{onboardingFriendCountMessage}

}\n {source === INVITE_FRIENDS && friendCount === 0 && (\n

{t('friend_list.no_fb_friends_on_strava')}

\n )}\n {friendCount > 0 && (\n \n {sortedFriends.map((friend) => (\n \n ))}\n \n )}\n \n );\n};\n\nexport default FacebookFriendList;\n","// extracted by mini-css-extract-plugin\nexport default {\"fb-panel\":\"FindFacebookFriends--fb-panel--xEyA+\",\"fbPanel\":\"FindFacebookFriends--fb-panel--xEyA+\",\"no-background\":\"FindFacebookFriends--no-background--2gPup\",\"noBackground\":\"FindFacebookFriends--no-background--2gPup\",\"center-spinner\":\"FindFacebookFriends--center-spinner--Wnal7\",\"centerSpinner\":\"FindFacebookFriends--center-spinner--Wnal7\"};","import React, { useEffect, useMemo, useReducer } from 'react';\nimport PropTypes from 'prop-types';\nimport { orderBy } from 'lodash-es';\nimport Spinner from '@strava/ui/Spinner';\nimport useFacebook from 'hooks/externalSocialPartners/useFacebook';\nimport { AuthorizationStatus } from 'hooks/externalSocialPartners/constants/auth-status-constants';\nimport StravaAlert from 'components/StravaAlert';\nimport { INVITE_FRIENDS, ONBOARDING } from '../utils/friendsConstants';\nimport { t } from '../utils/friendsUtils';\nimport FriendsContext from '../state/FriendsContext';\nimport { reducer } from '../state/friendsReducer';\nimport { ADD_ALERT, UPDATE_FRIENDS } from '../state/friendsActions';\nimport LinkFacebookAccount from '../components/LinkFacebookAccount';\nimport FacebookFriendList from '../components/FacebookFriendList';\n\nimport styles from './FindFacebookFriends.scss';\n\nconst FindFacebookFriends = ({\n track,\n currentAthlete,\n isVisible, // InviteFriends modal -> modalTablIndex === 1\n source, // 'invite_friends' or 'onboarding'\n fbApiProps,\n onFollowingFriendsChange\n}) => {\n const [state, dispatch] = useReducer(reducer, {\n currentAthlete,\n source,\n friends: {},\n followedFriends: {},\n alert: null,\n onFollowingFriendsChange\n });\n const { alert } = state;\n\n const providerState = useMemo(() => ({ state, dispatch, track }), [\n state,\n track\n ]);\n\n // don't have requestFriends be called as soon as FB script is ready. let athlete opt-in\n // to connecting FB in onboarding by clicking connect FB button\n const autoSync = source !== ONBOARDING;\n\n const { fbFriends, authorizationStatus, requestFriends } = useFacebook({\n ...fbApiProps,\n autoSync,\n source\n });\n\n useEffect(() => {\n // When component is visible, call requestFriends as soon as FB script is ready.\n // If user is not already logged in to FB, or if user is logged in to FB but\n // doesn't have the right permissions, auth status will be REQUEST_NEW_PERMISSIONS\n // and we show them the LinkFacebookAccount view\n if (\n autoSync &&\n isVisible &&\n authorizationStatus === AuthorizationStatus.READY\n ) {\n requestFriends();\n }\n // requestFriends deliberately left out to prevent multiple calls to this\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [authorizationStatus, isVisible]);\n\n // save friends to the shared state\n useEffect(() => {\n if (fbFriends.length > 0) {\n // INVITE_FRIENDS: list followable friends before friends already being followed\n // and sort alphabetically by name\n // ONBOARDING: list only followable friends\n const processedFriends =\n source === INVITE_FRIENDS\n ? orderBy(fbFriends, ['isFollowable', 'displayName'], ['desc', 'asc'])\n : fbFriends.filter((friend) => friend.isFollowable);\n // map friends array to object with the strava ids as the keys\n // save the index of the friend's position in the sorted array\n const friends = Object.fromEntries(\n processedFriends.map((friend, index) => [\n friend.id,\n { ...friend, sortedIndex: index }\n ])\n );\n dispatch({\n type: UPDATE_FRIENDS,\n payload: { friends }\n });\n }\n }, [dispatch, fbFriends, source]);\n\n useEffect(() => {\n if (authorizationStatus === AuthorizationStatus.ERROR) {\n // show error message to athlete when something goes wrong during authorization\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: { severity: 'error', message: t('errors.fb_error') }\n }\n });\n } else if (\n source === INVITE_FRIENDS &&\n authorizationStatus === AuthorizationStatus.UNAUTHORIZED\n ) {\n // INVITE_FRIENDS ONLY:\n // show warning message to athlete if they don't authorize FB permissions\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: {\n severity: 'warning',\n message: t('errors.unauthorized')\n }\n }\n });\n }\n }, [authorizationStatus, dispatch, source]);\n\n return (\n \n
\n {source === INVITE_FRIENDS && alert && (\n {alert.message}\n )}\n {source === ONBOARDING &&

{t('onboarding.message')}

}\n {[\n AuthorizationStatus.REQUEST_PERMISSIONS,\n AuthorizationStatus.REQUEST_NEW_PERMISSIONS,\n AuthorizationStatus.ERROR,\n AuthorizationStatus.UNAUTHORIZED\n ].includes(authorizationStatus) && (\n \n )}\n {source === ONBOARDING && alert && (\n \n {alert.message}\n \n )}\n {authorizationStatus === AuthorizationStatus.DATA_FETCHED && (\n \n )}\n {[\n AuthorizationStatus.INITIATED,\n AuthorizationStatus.READY,\n AuthorizationStatus.AUTHORIZED\n ].includes(authorizationStatus) && (\n
\n \n
\n )}\n
\n
\n );\n};\n\nFindFacebookFriends.defaultProps = {\n isVisible: true,\n onFollowingFriendsChange: () => {}\n};\n\nFindFacebookFriends.propTypes = {\n track: PropTypes.func.isRequired,\n currentAthlete: PropTypes.shape({\n id: PropTypes.number\n }).isRequired,\n fbApiProps: PropTypes.shape({\n appId: PropTypes.number,\n version: PropTypes.string,\n locale: PropTypes.string\n }).isRequired,\n source: PropTypes.oneOf([INVITE_FRIENDS, ONBOARDING]).isRequired,\n isVisible: PropTypes.bool,\n onFollowingFriendsChange: PropTypes.func\n};\n\nexport default FindFacebookFriends;\n","// extracted by mini-css-extract-plugin\nexport default {\"friend-list\":\"FriendList--friend-list--vRDGD\",\"friendList\":\"FriendList--friend-list--vRDGD\",\"scroll-shadow\":\"FriendList--scroll-shadow--0GFRE\",\"scrollShadow\":\"FriendList--scroll-shadow--0GFRE\"};","import React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from '@strava/ui/clsx';\nimport { useFriendsContext } from '../../../state/FriendsContext';\nimport { INVITE_FRIENDS } from '../../../utils/friendsConstants';\n\nimport styles from './FriendList.scss';\n\nconst FriendList = ({ children }) => {\n const { state } = useFriendsContext();\n const { followedFriends, onFollowingFriendsChange } = state;\n\n useEffect(() => {\n onFollowingFriendsChange(followedFriends);\n }, [onFollowingFriendsChange, followedFriends]);\n\n return (\n \n {children}\n \n );\n};\n\nFriendList.propTypes = {\n children: PropTypes.node.isRequired\n};\n\nexport default FriendList;\n","// extracted by mini-css-extract-plugin\nexport default {\"list-row\":\"AthleteInfo--list-row--bM5xg\",\"listRow\":\"AthleteInfo--list-row--bM5xg\",\"athlete-metadata\":\"AthleteInfo--athlete-metadata--qzuP+\",\"athleteMetadata\":\"AthleteInfo--athlete-metadata--qzuP+\",\"name-and-subtitle\":\"AthleteInfo--name-and-subtitle--t+CuJ\",\"nameAndSubtitle\":\"AthleteInfo--name-and-subtitle--t+CuJ\",\"grayed-out\":\"AthleteInfo--grayed-out--ay4VH\",\"grayedOut\":\"AthleteInfo--grayed-out--ay4VH\"};","import React from 'react';\nimport PropTypes from 'prop-types';\nimport Avatar from '@strava/ui/Avatar';\nimport clsx from '@strava/ui/clsx';\nimport { isMobile } from 'utils/generalUtils';\nimport { useFriendsContext } from '../../../state/FriendsContext';\nimport { INVITE_FRIENDS } from '../../../utils/friendsConstants';\n\nimport styles from './AthleteInfo.scss';\n\nconst AthleteInfo = ({ friend, children }) => {\n const { state } = useFriendsContext();\n return (\n
  • \n \n \n
    \n

    {friend.displayName}

    \n

    {friend.subtitle}

    \n
    \n \n {children}\n
  • \n );\n};\n\nAthleteInfo.propTypes = {\n friend: PropTypes.shape({\n isFollowable: PropTypes.bool,\n picture: PropTypes.string,\n badge: PropTypes.string,\n displayName: PropTypes.string,\n subtitle: PropTypes.string\n }).isRequired,\n children: PropTypes.node.isRequired\n};\n\nexport default AthleteInfo;\n","import { useEffect, useState } from 'react';\nimport {\n FOLLOW_ACTIONS,\n FOLLOWING_STATUS\n} from 'constants/follows/following-constants';\n\nexport const useCtaAction = (friend) => {\n const { approveFollowers, followingStatus } = friend;\n const [cta, setCta] = useState(FOLLOW_ACTIONS.follow);\n\n useEffect(() => {\n if (followingStatus === FOLLOWING_STATUS.pending) {\n setCta(FOLLOW_ACTIONS.followRequested);\n } else if (followingStatus === FOLLOWING_STATUS.following) {\n setCta(FOLLOW_ACTIONS.following);\n } else {\n setCta(\n approveFollowers\n ? FOLLOW_ACTIONS.requestToFollow\n : FOLLOW_ACTIONS.follow\n );\n }\n }, [approveFollowers, followingStatus]);\n\n return cta;\n};\n\nexport default useCtaAction;\n","import React, { useState } from 'react';\nimport PropTypes from 'prop-types';\nimport Button from '@strava/ui/Button';\nimport { FOLLOWING_STATUS } from 'constants/follows/following-constants';\nimport { followAthlete, unfollowAthlete } from 'api/athlete';\nimport AthleteInfo from '../AthleteInfo';\nimport { useFriendsContext } from '../../../state/FriendsContext';\nimport {\n ADD_ALERT,\n CLEAR_ALERT,\n ADD_ATHLETE,\n REMOVE_ATHLETE,\n UPDATE_FRIEND_FOLLOWING_STATUS\n} from '../../../state/friendsActions';\nimport { t } from '../../../utils/friendsUtils';\nimport {\n INVITE_FRIENDS,\n SUGGESTED_FRIENDS\n} from '../../../utils/friendsConstants';\nimport useCtaAction from '../../../utils/useCtaAction';\n\nconst FriendListItem = ({ id }) => {\n // retrieve friend from shared state\n const { state, dispatch, track } = useFriendsContext();\n const { friends, currentAthlete, source } = state;\n const friend = friends[id];\n const [isProcessing, setIsProcessing] = useState(false);\n\n const cta = useCtaAction(friend);\n\n const handleFollowAthlete = () => {\n followAthlete({\n followerId: currentAthlete.id,\n followingId: friend.id\n })\n .then((status) => {\n const analytics = {\n element: source === INVITE_FRIENDS ? `${cta}_btn` : cta,\n action: 'click',\n properties: {\n athlete_id: friend.id,\n following_status: status\n }\n };\n if (source === INVITE_FRIENDS) {\n analytics.properties.current_tab = 'facebook';\n }\n track(analytics);\n if (status === FOLLOWING_STATUS.error) {\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: { severity: 'error', message: t(`errors.generic`) }\n }\n });\n } else {\n dispatch({\n type: UPDATE_FRIEND_FOLLOWING_STATUS,\n payload: {\n id: friend.id,\n isFollowable: false,\n followingStatus: status\n }\n });\n dispatch({\n type: ADD_ATHLETE,\n payload: { friend }\n });\n }\n })\n .finally(() => {\n setIsProcessing(false);\n });\n };\n\n const handleUnfollowAthlete = () => {\n unfollowAthlete({\n followerId: currentAthlete.id,\n followingId: friend.id\n })\n .then((success) => {\n track({\n action: 'click',\n element: 'unfollow',\n properties: {\n athlete_id: friend.id,\n success\n }\n });\n if (success) {\n dispatch({\n type: UPDATE_FRIEND_FOLLOWING_STATUS,\n payload: {\n id: friend.id,\n isFollowable: true,\n followingStatus: friend.approveFollowers\n ? FOLLOWING_STATUS.canRequest\n : FOLLOWING_STATUS.canFollow\n }\n });\n dispatch({\n type: REMOVE_ATHLETE,\n payload: {\n id: friend.id\n }\n });\n } else {\n dispatch({\n type: ADD_ALERT,\n payload: {\n alert: { severity: 'error', message: t(`errors.generic`) }\n }\n });\n }\n })\n .finally(() => {\n setIsProcessing(false);\n });\n };\n\n const handleBtnClick = () => {\n setIsProcessing(true);\n dispatch({ type: CLEAR_ALERT });\n\n if (friend.isFollowable) {\n handleFollowAthlete();\n } else {\n handleUnfollowAthlete();\n }\n };\n\n return (\n \n \n {t(`cta_actions.${cta}`)}\n \n \n );\n};\n\nFriendListItem.propTypes = {\n id: PropTypes.number.isRequired\n};\n\nexport default FriendListItem;\n","import { useContext, createContext } from 'react';\n\nconst FriendsContext = createContext();\nFriendsContext.displayName = 'FriendsContext';\n\nexport const useFriendsContext = () => {\n const context = useContext(FriendsContext);\n\n if (!context) {\n throw new Error(\n 'useFriendsContext must be used within the FriendsContext.Provider'\n );\n }\n\n return context;\n};\n\nexport default FriendsContext;\n","export const ADD_ALERT = 'ADD_ALERT';\nexport const CLEAR_ALERT = 'CLEAR_ALERT';\nexport const ADD_ATHLETE = 'ADD_ATHLETE';\nexport const REMOVE_ATHLETE = 'REMOVE_ATHLETE';\nexport const UPDATE_FRIENDS = 'UPDATE_FRIENDS';\nexport const UPDATE_FRIEND_FOLLOWING_STATUS = 'UPDATE_FRIEND_FOLLOWING_STATUS';\n\nexport default {\n ADD_ALERT,\n CLEAR_ALERT,\n ADD_ATHLETE,\n REMOVE_ATHLETE,\n UPDATE_FRIENDS,\n UPDATE_FRIEND_FOLLOWING_STATUS\n};\n","import {\n ADD_ALERT,\n CLEAR_ALERT,\n ADD_ATHLETE,\n REMOVE_ATHLETE,\n UPDATE_FRIENDS,\n UPDATE_FRIEND_FOLLOWING_STATUS\n} from './friendsActions';\n\nexport const reducer = (state, action) => {\n switch (action.type) {\n case ADD_ALERT: {\n const { alert } = action.payload;\n return {\n ...state,\n alert\n };\n }\n case CLEAR_ALERT: {\n return {\n ...state,\n alert: null\n };\n }\n case ADD_ATHLETE: {\n const { friend } = action.payload;\n return {\n ...state,\n followedFriends: {\n ...state.followedFriends,\n [friend.id]: friend\n }\n };\n }\n case REMOVE_ATHLETE: {\n const { id } = action.payload;\n const { [id]: _, ...rest } = state.followedFriends;\n return {\n ...state,\n followedFriends: { ...rest }\n };\n }\n case UPDATE_FRIENDS: {\n const { friends } = action.payload;\n return {\n ...state,\n friends\n };\n }\n case UPDATE_FRIEND_FOLLOWING_STATUS: {\n const { id, isFollowable, followingStatus } = action.payload;\n const friend = state.friends[id];\n return {\n ...state,\n friends: {\n ...state.friends,\n [id]: { ...friend, isFollowable, followingStatus }\n }\n };\n }\n default:\n throw new Error(`${action.type} not recognized`);\n }\n};\n\nexport default { reducer };\n","export const ONBOARDING = 'onboarding';\nexport const INVITE_FRIENDS = 'invite_friends';\nexport const SUGGESTED_FRIENDS = 'suggested_friends';\n\nexport default { ONBOARDING, INVITE_FRIENDS, SUGGESTED_FRIENDS };\n","import I18n from 'utils/I18n';\n\nexport const t = (key, params) =>\n I18n.t(`components.friends.${key}`, { ...params });\n\nexport default { t };\n","export const ALERT_TYPES = Object.freeze({\n warning: 'warning',\n error: 'error',\n info: 'info',\n success: 'success'\n});\n\nexport default { ALERT_TYPES };\n","export const FOLLOWING_STATUS = Object.freeze({\n following: 'following',\n pending: 'pending',\n error: 'error',\n canFollow: 'can_follow',\n canRequest: 'can_request'\n});\n\nexport const FOLLOW_ACTIONS = Object.freeze({\n add: 'add',\n followRequested: 'follow_requested',\n following: 'following',\n requestToFollow: 'request_to_follow',\n follow: 'follow'\n});\n","import { replace } from 'lodash-es';\nimport { logError } from './utils/sentry';\n\nconst appendScriptToBody = ({ script, name }) => {\n if (document.querySelector('body')) {\n document.querySelector('body').appendChild(script);\n } else {\n const e = new Error(`Failed to inject ${name} script`);\n logError(e);\n }\n};\n\n// this injects window.google and not the legacy window.gapi JS api\nexport const injectGoogleScript = (callback) => {\n if (!window.google) {\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.onload = callback;\n script.id = 'google-client-script';\n appendScriptToBody({ script, name: 'google gsi' });\n } else {\n callback();\n }\n};\n\nexport const injectAppleScript = (locale = 'en_US') => {\n if (!window.apple) {\n const script = window.document.createElement('script');\n const formattedLocale = replace(locale, '-', '_');\n script.src = `https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/${formattedLocale}/appleid.auth.js`;\n script.async = true;\n appendScriptToBody({ script, name: 'apple' });\n }\n};\n\nexport const injectFacebookScript = ({\n appId,\n version,\n callback,\n locale = 'en_US'\n}) => {\n if (!window.FB) {\n window.fbAsyncInit = () => {\n // ref - https://developers.facebook.com/docs/javascript/reference/FB.init/v13.0\n window.FB.init({\n appId,\n xfbml: true,\n version,\n status: true,\n cookie: true\n });\n callback();\n };\n\n // facebook uses format ll_CC - see https://developers.facebook.com/docs/javascript/internationalization\n const formattedLocale = replace(locale, '-', '_');\n\n const script = window.document.createElement('script');\n script.src = `https://connect.facebook.net/${formattedLocale}/sdk.js`;\n script.async = true;\n appendScriptToBody({ script, name: 'facebook-jssdk' });\n } else {\n callback();\n }\n};\n\nexport default { injectGoogleScript, injectAppleScript, injectFacebookScript };\n","/**\n * AUTHORIZED - the athlete has granted all the necessary permissions and is ready to fetch data\n * DATA_FETCHED - the athlete has granted all the necessary permissions and data has been fetched successfully\n * ERROR - an error occurred while fetching or processing data\n * INITIATED - social hook has been attached to the component\n * READY - external partner JS has been injected or verified to be present on the page\n * REQUEST_PERMISSION - athlete needs to grant permissions for the request to take place\n * REQUEST_NEW_PERMISSION - the athlete needs to grant more permissions for the request to proceed\n * UNAUTHORIZED - the athlete has denied giving permissions after being prompted to do so\n */\nexport const AuthorizationStatus = Object.freeze({\n AUTHORIZED: 'AUTHORIZED',\n DATA_FETCHED: 'DATA_FETCHED',\n ERROR: 'ERROR',\n INITIATED: 'INITIATED',\n READY: 'READY',\n REQUEST_PERMISSIONS: 'REQUEST_PERMISSIONS',\n REQUEST_NEW_PERMISSIONS: 'REQUEST_NEW_PERMISSIONS',\n UNAUTHORIZED: 'UNAUTHORIZED'\n});\n\nexport default { AuthorizationStatus };\n","import { split } from 'lodash-es';\n\nexport { timeout } from './devUtils';\n\nexport const generateRandomId = () =>\n Math.random()\n .toString(36)\n .substring(2);\n\n// Capitalizes all the words and replaces some characters in the string to create a nicer looking title.\n// eg. 'man from the boondocks' => 'Man From The Boondocks'\nconst titleize = (str) =>\n str.replace(\n /\\w\\S*/g,\n (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()\n );\n\nexport const displayName = (\n { firstName = '', lastName = '' },\n options = { forceAnonymize: false, maxLength: 100 }\n) => {\n const { maxLength, forceAnonymize } = options;\n const fullName = `${firstName} ${lastName}`;\n\n if (forceAnonymize || fullName.length > maxLength) {\n if (firstName.length > maxLength - 3) {\n return `${titleize(\n firstName.substring(0, maxLength - 4)\n )}... ${lastName.charAt(0).toUpperCase()}.`;\n }\n return `${titleize(firstName)} ${lastName.charAt(0).toUpperCase()}.`;\n }\n return fullName.trim();\n};\n\nexport const isMobile = () => window.navigator.userAgent.includes('Mobile');\n\nexport const dateYearsAgo = (years) => {\n const d = new Date(new Date().toDateString());\n d.setFullYear(d.getFullYear() - years);\n return d;\n};\n\nexport const parseServerDateString = (date) => {\n const dobArray = split(date, '-');\n return {\n year: parseInt(dobArray[0], 10),\n month: parseInt(dobArray[1], 10),\n day: parseInt(dobArray[2], 10)\n };\n};\n\nexport default {\n displayName,\n generateRandomId,\n isMobile,\n dateYearsAgo,\n parseServerDateString\n};\n","import axios from 'axios';\n\nfunction baseUrl() {\n const port = window.location.port === '' ? '' : `:${window.location.port}`;\n\n return `${window.location.protocol}//${window.location.hostname}${port}`;\n}\n\nexport function csrfToken() {\n return document\n .querySelector('meta[name=\"csrf-token\"]')\n .getAttribute('content');\n}\n\nexport default function createNetworkingClient(options = {}) {\n return axios.create({\n baseUrl: baseUrl(),\n timeout: 5000,\n headers: {\n 'X-Requested-With': 'XMLHttpRequest',\n 'X-CSRF-TOKEN': csrfToken()\n },\n ...options\n });\n}\n"],"names":["followAthlete","followerId","followingId","Promise","resolve","createNetworkingClient","post","follow","follower_id","following_id","then","response","status","StatusCodes","data","approved","FOLLOWING_STATUS","catch","bulkFollow","followeeIds","followee_ids","success","ids","followed_athlete_ids","followedAthleteIds","e","logError","unfollowAthlete","delete","headers","Accept","getSuggestedFollows","callsite","reject","get","params","error","UrlResendVerificationEmail","EmailVerificationCTA","state","modalIsOpen","resendEmailInProgress","resendEmail","setState","closeModal","componentDidMount","this","props","resendOnMount","render","children","className","email","optionalExplanation","cta","onClick","styles","I18n","Modal","isOpen","onRequestClose","title","pending_email","class_name","email_settings_path","React","defaultProps","NotificationEmailVerificationCTA","iconURL","text","src","alt","StravaAlert","severity","options","clsx","I18nPrefix","t","key","InviteFriendsContext","useInviteFriendsContext","displayName","ADD_ALERT","CHANGE_TAB","CLEAR_ALERT","CLEAR_EMAILS","CLOSE_MODAL","OPEN_MODAL","UPDATE_EMAILS","UPDATE_FB_FRIENDS","UPDATE_FB_FRIEND_FOLLOWING_STATUS","UPDATE_INVITED_EMAILS_LIST","clientId","mocked","useState","contacts","setContacts","undefined","token","setToken","AuthorizationStatus","authorizationStatus","setAuthorizationStatus","handleSignInContactsScope","tokenResponse","access_token","accessToken","window","google","accounts","oauth2","hasGrantedAllScopes","Authorization","url","PEOPLE_BASE_URL","connections","c","timeout","revoke","useEffect","injectGoogleScript","id","cancel","requestContacts","scope","callback","initTokenClient","client_id","requestAccessToken","disconnect","isNil","dispatch","track","type","element","action","properties","current_tab","getPrimaryEntry","entries","primary","find","entry","metadata","isEmpty","processContactsForUI","processedContacts","map","index","names","emailAddresses","photos","displayContact","isOnStrava","value","name","picture","compact","extractEmailsFromString","emails","split","toLower","trim","contact","FOLLOW_ACTIONS","disabled","config","setConfig","followingStatus","currentFollowingStatus","setCurrentFollowingStatus","isLoading","setIsLoading","currentAthlete","invitedEmailsList","approveFollowers","includes","prev","disabledTextStyle","Avatar","size","badge","Button","variant","athlete_id","separator","payload","concat","alert","message","finally","handleBtnClick","ResultsFeed","results","Spinner","length","searchKeyword","setSearchKeyword","filterResults","setFilterResults","initialResults","useRef","current","contacts_count","already_on_strava_count","filter","onChange","keyword","target","toLowerCase","placeholder","safeDispatch","useSafeDispatch","googleClientId","useGoogle","useSafeState","setProcessedContacts","isProcessingContacts","setIsProcessingContacts","isSendingEmails","setIsSendingEmails","emailInputRef","emailMessage","dispatchAlert","useCallback","uniqBy","remove","importedEmails","forEach","friend","approve_followers","following_status","display_name","orderBy","focus","alreadyOnStravaMessage","alreadyOnStrava","numOnStrava","email_address","escape","other_email_address","count","isValidEmailList","emailList","EmailValidator","handleFormSubmission","event","preventDefault","email_count","is_valid_email_list","toString","i","to","body","invite_dialog","sent","notSent","not_sent","already_on_strava","noWrap","content","onSubmit","htmlFor","ref","isModalOpen","modalTabIndex","fbAppId","fbVersion","locale","ModalWithTabs","onDismiss","selectedTab","FindFacebookFriends","source","INVITE_FRIENDS","fbApiProps","appId","version","isVisible","reducer","fbFriends","isFollowable","Error","InviteFriendsButton","defaultTabIndex","useInView","threshold","intersectionObserverRef","inView","fields","trackV2","page","category","default_tab","useReducer","providerState","useMemo","logo","cx","camelCase","customStyles","overlay","zIndex","afterOpen","beforeClose","closeTimeoutMS","shouldCloseOnOverlayClick","ariaHideApp","bodyOpenClassName","overlayClassName","base","style","dialogClassName","onAfterOpen","Permissions","Object","freeze","FRIEND_LIST","autoSync","setFbFriends","isInitialRequest","setIsInitialRequest","injectFacebookScript","checkPermissions","grantedScopes","requestedScopes","difference","getGrantedScopes","p","permission","requestPermissions","FB","getLoginStatus","authResponse","isDev","module","default","stravaFbProxyPostPermissions","hasPermissions","return_scopes","auth_type","login","grantedScopesList","fbGraphApiLogin","requestFriends","stravaFbProxyPostFriends","fbData","facebookUIDs","facebook_uids","stravaUsersFromFbIds","stravaData","camelCaseFriends","athlete","subtitle","display_location","LinkFacebookButton","fullWidth","LogosFacebookSmall","useFriendsContext","isInviteFriends","analyticsBySource","authorization_status","sortedFriends","isProcessing","setIsProcessing","handleFollowAll","friends","UPDATE_FRIEND_FOLLOWING_STATUS","follow_all_count","follow_all_status","some","sortBy","values","friendCount","onboardingFriendCountMessage","friend_count","initialScreenEnter","analytics","friends_count","ONBOARDING","FriendList","FriendListItem","onFollowingFriendsChange","followedFriends","useFacebook","processedFriends","fromEntries","sortedIndex","UPDATE_FRIENDS","FriendsContext","isMobile","flexShrink","setCta","useCtaAction","SUGGESTED_FRIENDS","ADD_ATHLETE","REMOVE_ATHLETE","createContext","context","useContext","rest","ALERT_TYPES","warning","info","following","pending","canFollow","canRequest","add","followRequested","requestToFollow","appendScriptToBody","script","document","querySelector","appendChild","createElement","async","onload","injectAppleScript","apple","formattedLocale","replace","fbAsyncInit","init","xfbml","cookie","AUTHORIZED","DATA_FETCHED","ERROR","INITIATED","READY","REQUEST_PERMISSIONS","REQUEST_NEW_PERMISSIONS","UNAUTHORIZED","generateRandomId","Math","random","substring","titleize","str","txt","charAt","toUpperCase","substr","firstName","lastName","forceAnonymize","maxLength","fullName","navigator","userAgent","dateYearsAgo","years","d","Date","toDateString","setFullYear","getFullYear","parseServerDateString","date","dobArray","year","parseInt","month","day","csrfToken","getAttribute","axios","baseUrl","port","location","protocol","hostname"],"sourceRoot":""}