{"version":3,"file":"js/85943-0b035637a804bb79a498.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/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/follows/following-constants.js","webpack://StravaModern/./app/javascript/hooks/externalSocialPartners/constants/auth-status-constants.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 {\"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 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","/**\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"],"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","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","clsx","Button","variant","athlete_id","separator","payload","concat","alert","severity","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","StravaAlert","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","options","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","following","pending","canFollow","canRequest","add","followRequested","requestToFollow","AUTHORIZED","DATA_FETCHED","ERROR","INITIATED","READY","REQUEST_PERMISSIONS","REQUEST_NEW_PERMISSIONS","UNAUTHORIZED"],"sourceRoot":""}