{"version":3,"file":"js/94010-073e698a82c0046fbccc.js","mappings":"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","sources":["webpack://StravaModern/./app/javascript/api/athlete/athlete.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/analytics.js","webpack://StravaModern/./app/javascript/utils/dev-utils.js","webpack://StravaModern/./app/javascript/utils/general-utils.js","webpack://StravaModern/./app/javascript/utils/networking-client.js"],"sourcesContent":["import createNetworkingClient from 'utils/networking-client';\nimport { devLog } from 'utils/dev-utils';\nimport { StatusCodes } from 'http-status-codes';\nimport { FOLLOWING_STATUS } from '../../constants/follows/following-constants';\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 devLog(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 devLog(response);\n resolve(false);\n }\n })\n .catch((e) => {\n devLog(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 devLog(response.error);\n resolve(response.error);\n }\n })\n .catch((e) => {\n devLog(e);\n reject(e);\n });\n });\n};\n\nexport default { followAthlete, unfollowAthlete, getSuggestedFollows };\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/dev-utils';\nimport { AuthorizationStatus } from './constants/auth-status-constants';\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); // TODO : log sentry error in the monorepo\n }\n })\n .catch(() => {\n setAuthorizationStatus(AuthorizationStatus.ERROR); // TODO : log sentry error in the monorepo\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/general-utils';\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';\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 // TODO: log sentry error\n dispatchAlert({\n severity: 'error',\n message: t('modal.errors.generic')\n });\n }\n })\n .catch(() => {\n // TODO: log sentry error\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/dev-utils';\nimport { FOLLOWING_STATUS } from 'constants/follows/following-constants';\nimport { AuthorizationStatus } from './constants/auth-status-constants';\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 {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, source }) => {\n const [authorizationStatus, setAuthorizationStatus] = useState(\n AuthorizationStatus.INITIATED\n );\n const [fbFriends, setFbFriends] = useState([]);\n\n /**\n * 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 *\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 (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(() => {\n // something went wrong while retrieving or processing Strava athletes from FB data\n setAuthorizationStatus(AuthorizationStatus.ERROR); // TODO : log sentry error in the monorepo\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(() => {\n // something went wrong while retrieving or processing friend data\n setAuthorizationStatus(AuthorizationStatus.ERROR); // TODO : log sentry error in the monorepo\n });\n }\n })\n .catch(() => {\n // something went wrong while requesting or checking permissions\n setAuthorizationStatus(AuthorizationStatus.ERROR); // TODO : log sentry error in the monorepo\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 const { fbFriends, authorizationStatus, requestFriends } = useFacebook({\n ...fbApiProps,\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 (isVisible && authorizationStatus === AuthorizationStatus.READY) {\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_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/general-utils';\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';\n\n// eslint-disable-next-line no-unused-vars\nconst logError = (e) => {\n // TODO log error in monorepo sentry\n // console.error(e);\n};\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_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_NEW_PERMISSIONS: 'REQUEST_NEW_PERMISSIONS',\n UNAUTHORIZED: 'UNAUTHORIZED'\n});\n\nexport default { AuthorizationStatus };\n","export function trackV2({ category, page, action, element, properties = {} }) {\n try {\n window.Strava.ExternalAnalytics.trackV2({\n category,\n page,\n action,\n element,\n properties\n });\n } catch (e) {\n console.error(\n `Could not execute Strava.ExternalAnalytics.trackV2 event with the category:action ${category}:${action}`,\n e\n );\n }\n}\n\nexport default {\n trackV2\n};\n","/**\n * dev utils to make local development easier (dynamically-imported mock data,\n * dev-only console logs, etc.)\n */\n\nexport const isDev = () => {\n return process.env.NODE_ENV === 'development';\n};\n\nexport const isTest = () => process.env.NODE_ENV === 'test';\n\nexport const devLog = (string) => {\n if (isDev()) {\n // eslint-disable-next-line no-console\n console.log(string);\n }\n};\n\nexport const timeout = (ms) => {\n return new Promise((resolve) => setTimeout(resolve, ms));\n};\n\nexport default { isDev, devLog, timeout };\n","import { split } from 'lodash-es';\n\nexport { timeout } from './dev-utils';\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","devLog","unfollowAthlete","delete","headers","Accept","getSuggestedFollows","callsite","reject","get","params","error","StravaAlert","children","className","severity","options","clsx","styles","defaultProps","I18nPrefix","t","key","I18n","InviteFriendsContext","React","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","alt","connections","c","timeout","revoke","useEffect","injectGoogleScript","id","cancel","requestContacts","scope","callback","initTokenClient","client_id","requestAccessToken","disconnect","isNil","dispatch","track","type","onClick","element","action","properties","current_tab","getPrimaryEntry","entries","primary","find","entry","metadata","isEmpty","processContactsForUI","processedContacts","map","index","names","emailAddresses","photos","displayContact","isOnStrava","email","value","name","picture","compact","extractEmailsFromString","emails","split","toLower","trim","contact","FOLLOW_ACTIONS","disabled","config","setConfig","followingStatus","currentFollowingStatus","setCurrentFollowingStatus","isLoading","setIsLoading","state","currentAthlete","invitedEmailsList","approveFollowers","includes","prev","disabledTextStyle","Avatar","src","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","isOpen","onDismiss","title","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","cta","logo","cx","camelCase","customStyles","overlay","zIndex","afterOpen","beforeClose","Modal","props","closeTimeoutMS","onRequestClose","shouldCloseOnOverlayClick","ariaHideApp","bodyOpenClassName","overlayClassName","base","style","dialogClassName","onAfterOpen","Permissions","Object","freeze","FRIEND_LIST","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_NEW_PERMISSIONS","UNAUTHORIZED","Strava","ExternalAnalytics","console","process","string","log","ms","setTimeout","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":""}