Skip to content

Commit

Permalink
Merge pull request #455 from seasons/feature/collection-rail
Browse files Browse the repository at this point in the history
feature: Adds collections & uploads Apollo to version 3
  • Loading branch information
kierangillen authored Feb 4, 2021
2 parents f690227 + 5666e37 commit c6f3795
Show file tree
Hide file tree
Showing 94 changed files with 1,193 additions and 645 deletions.
8 changes: 2 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import App from "./src"
import { AppRegistry } from "react-native"
import * as Sentry from "@sentry/react-native"
import "react-native-gesture-handler"
// import { enableScreens } from "react-native-screens"

// This enables the native stack navigator using (react-native-screens)
// https://reactnavigation.org/blog/2020/02/06/react-navigation-5.0/#native-stack-navigator
// Leaving it commented out for now because there's glitch when navigating to the Product view
// enableScreens()
// "core-js/features/promise" is a polyfill Apollo refetch in RN, see: https://github.com/apollographql/apollo-client/issues/6381
import "core-js/features/promise"

AppRegistry.registerComponent("seasons", () => App)
8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
},
"dependencies": {
"@apollo/client": "^3.3.7",
"@apollo/react-hooks": "^3.1.1",
"@expo/react-native-action-sheet": "^3.8.0",
"@material-ui/core": "^4.11.1",
"@react-native-community/async-storage": "~1.12.0",
Expand All @@ -45,25 +44,22 @@
"@sentry/react-native": "^1.1.0",
"@types/jest": "^24.0.18",
"@types/luxon": "^1.24.3",
"apollo-boost": "^0.4.4",
"apollo-cache": "^1.3.2",
"apollo-cache-inmemory": "^1.6.6",
"apollo-cache-persist": "^0.1.1",
"apollo-client": "2.6.4",
"apollo-link": "^1.2.12",
"apollo-link-context": "^1.0.19",
"apollo-link-error": "^1.1.12",
"apollo-link-error": "^1.1.13",
"apollo-upload-client": "^14.1.1",
"apollo-utilities": "^1.3.2",
"aws-sdk": "^2.639.0",
"core-js": "^3.8.3",
"expo": "^39.0.0",
"graphql": "^14.5.8",
"lodash": "^4.17.15",
"luxon": "^1.21.1",
"node-fetch": "^2.6.0",
"querystring": "^0.2.0",
"react": "16.13.1",
"react-apollo": "^3.1.1",
"react-dom": "16.13.1",
"react-native": "0.63.3",
"react-native-animatable": "^1.3.3",
Expand Down
78 changes: 42 additions & 36 deletions src/Apollo/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
import { InMemoryCache, IntrospectionFragmentMatcher } from "apollo-cache-inmemory"
import { persistCache } from "apollo-cache-persist"
import { ApolloClient } from "apollo-client"
import { ApolloLink, Observable } from "apollo-link"
import { ApolloLink, Observable, ApolloClient, InMemoryCache, HttpLink } from "@apollo/client"
import { setContext } from "apollo-link-context"
import { onError } from "apollo-link-error"
import { createUploadLink } from "apollo-upload-client"
import { getAccessTokenFromSession, getNewToken } from "App/utils/auth"
import { config, Env } from "App/utils/config"
import { Platform } from "react-native"
import unfetch from "unfetch"

import AsyncStorage from "@react-native-community/async-storage"
import * as Sentry from "@sentry/react-native"

import introspectionQueryResultData from "../fragmentTypes.json"
import { resolvers, typeDefs } from "./resolvers"
import { isEmpty } from "lodash"

export const setupApolloClient = async () => {
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
fitPicsCount: {
read(newCount) {
return newCount
},
},
fitPics: {
merge(existing = [], incoming = [], { args: { skipFitPics = 0 } }) {
const merged = existing ? existing.slice(0) : []
for (let i = 0; i < incoming.length; ++i) {
merged[skipFitPics + i] = incoming[i]
}
existing = merged
return existing
},
},
productsConnection: {
merge(existing = {}, incoming = {}, { args: { skip = 0 } }) {
let mergedEdges = !isEmpty(existing) ? existing?.edges?.slice(0) : []
if (incoming?.edges?.length > 0) {
for (let i = 0; i < incoming?.edges?.length; ++i) {
mergedEdges[skip + i] = incoming?.edges?.[i]
}
}
return { ...existing, ...incoming, edges: mergedEdges }
},
},
},
},
},
})

const cache = new InMemoryCache({ fragmentMatcher })

const link = createUploadLink({
uri: config.get(Env.MONSOON_ENDPOINT) || "http://localhost:4000/",
// FIXME: unfetch here is being used for this fix https://github.com/jhen0409/react-native-debugger/issues/432
fetch: unfetch,
})
const httpLink = new HttpLink({
uri: process.env.MONSOON_ENDPOINT || "http://localhost:4000/", // Server URL (must be absolute)
}) as any

const authLink = setContext(async (_, { headers: oldHeaders }) => {
const headers = { ...oldHeaders, application: "harvest", platform: Platform.OS }
Expand All @@ -49,6 +67,7 @@ export const setupApolloClient = async () => {
// return the headers to the context so createUploadLink can read them
})

// @ts-ignore
const errorLink = onError(({ graphQLErrors, networkError, operation, forward, response }) => {
if (graphQLErrors) {
console.log("graphQLErrors", graphQLErrors)
Expand Down Expand Up @@ -78,7 +97,7 @@ export const setupApolloClient = async () => {
if (networkError) {
console.log("networkError", JSON.stringify(networkError))
// User access token has expired
if (networkError.statusCode === 401) {
if ((networkError as any).statusCode === 401) {
// We assume we have both tokens needed to run the async request
// Let's refresh token through async request
return new Observable((observer) => {
Expand Down Expand Up @@ -112,25 +131,12 @@ export const setupApolloClient = async () => {
}
})

const accessToken = await getAccessTokenFromSession()
cache.writeData({
data: {
isLoggedIn: !!accessToken,
localBagItems: [],
},
})

await persistCache({
cache,
storage: AsyncStorage,
})

return new ApolloClient({
// Provide required constructor fields
cache,
link: ApolloLink.from([authLink, errorLink, link]),
link: ApolloLink.from([authLink, errorLink, httpLink]) as any,
typeDefs,
resolvers,
cache,
// Provide some optional constructor fields
name: "react-web-client",
version: "1.3",
Expand Down
3 changes: 1 addition & 2 deletions src/Apollo/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export const typeDefs = gql`
variantID: ID!
}
extend type Query {
isLoggedIn: Boolean!
localBagItems: [LocalProduct!]!
isInBag(productID: ID!): Boolean!
}
Expand All @@ -28,7 +27,7 @@ interface AppResolvers extends Resolvers {
// We will update this with our app's resolvers later
}

export const resolvers = {
export const resolvers: any = {
localBagItems: (_, __, { cache }) => {
const queryResult = cache.readQuery({
query: GET_LOCAL_BAG,
Expand Down
19 changes: 16 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import DeviceInfo from "react-native-device-info"
import { SafeAreaProvider } from "react-native-safe-area-context"
import { enableScreens } from "react-native-screens"
import stripe from "tipsi-stripe"

import { ApolloProvider } from "@apollo/react-hooks"
import { ApolloProvider, gql } from "@apollo/client"
import AsyncStorage from "@react-native-community/async-storage"
import * as Sentry from "@sentry/react-native"

import { setupApolloClient } from "./Apollo"
import { NetworkProvider } from "./NetworkProvider"
import { config, Env } from "./utils/config"
Expand All @@ -22,6 +20,21 @@ export const App = () => {
async function loadClient() {
await config.start()
const client = await setupApolloClient()

client.writeQuery({
query: gql`
query InitializeLocalCache {
localBagItems {
productID
variantID
}
}
`,
data: {
localBagItems: [],
},
})

setApolloClient(client)

if (!__DEV__) {
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Pause/PauseButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useState } from "react"
import { Linking } from "react-native"
import { ButtonVariant } from "../Button"
import { usePopUpContext } from "App/Navigation/ErrorPopUp/PopUpContext"
import { useMutation } from "react-apollo"
import { useMutation } from "@apollo/client"
import gql from "graphql-tag"
import { DateTime } from "luxon"
import { GET_MEMBERSHIP_INFO } from "App/Scenes/Account/MembershipInfo/MembershipInfo"
Expand Down
14 changes: 11 additions & 3 deletions src/Navigation/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import analytics from "@segment/analytics-react-native"

import AuthContext from "./AuthContext"
import { ModalAndMainScreens } from "./Stacks"
import { gql } from "@apollo/client"

// For docs on auth see: https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

Expand Down Expand Up @@ -104,13 +105,20 @@ export const AuthProvider = React.forwardRef<AuthProviderRef, AuthProviderProps>
await AsyncStorage.removeItem("beamsData")
RNPusherPushNotifications.clearAllState()
apolloClient.resetStore()
analytics.reset()
apolloClient.writeData({
apolloClient.writeQuery({
query: gql`
query ResetLocalCache {
localBagItems {
productID
variantID
}
}
`,
data: {
isLoggedIn: false,
localBagItems: [],
},
})
analytics.reset()
dispatch({ type: "SIGN_OUT" })
},
resetStore: () => {
Expand Down
2 changes: 1 addition & 1 deletion src/Navigation/ErrorPopUp/PopUpContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PopUpData } from "@seasons/eclipse"
import React, { useContext } from "react"
import { PopUpData } from "./PopUpProvider"

export const usePopUpContext = () => useContext(PopUpContext)

Expand Down
12 changes: 1 addition & 11 deletions src/Navigation/ErrorPopUp/PopUpProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { PopUpData } from "@seasons/eclipse"
import React, { useReducer } from "react"
import PopUpContext from "./PopUpContext"

export interface PopUpData {
title?: string
icon?: JSX.Element
note?: string
buttonText?: string
onClose: any
theme?: "light" | "dark"
secondaryButtonText?: string
secondaryButtonOnPress?: () => void
}

enum PopUpAction {
Show = "SHOW",
Hide = "HIDE",
Expand Down
6 changes: 6 additions & 0 deletions src/Navigation/Stacks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SurpriseMe } from "App/Scenes/Bag/SurpriseMe"
import { Brand } from "App/Scenes/Brand"
import { Brands } from "App/Scenes/Brands"
import { Browse, Filters } from "App/Scenes/Browse"
import { CollectionScene } from "App/Scenes/Collection"
import { CreateAccount } from "App/Scenes/CreateAccount"
import { ApplyPromoCode } from "App/Scenes/CreateAccount/Admitted/ApplyPromoCode/ApplyPromoCode"
import { DebugMenu } from "App/Scenes/DebugMenu"
Expand Down Expand Up @@ -149,6 +150,11 @@ const HomeStackScreen = () => {
<HomeStack.Screen name={Schema.PageNames.Home} component={Home} />
<HomeStack.Screen name={Schema.PageNames.Product} component={Product} initialParams={{ id: "" }} />
<HomeStack.Screen name={Schema.PageNames.Brand} component={Brand} initialParams={{ id: "" }} />
<HomeStack.Screen
name={Schema.PageNames.Collection}
component={CollectionScene}
initialParams={{ collectionSlug: "" }}
/>
<HomeStack.Screen name={Schema.PageNames.Tag} component={Tag} />
<HomeStack.Screen name={Schema.PageNames.Brands} component={Brands} />
<HomeStack.Screen name={Schema.PageNames.Webview} component={Webview} />
Expand Down
1 change: 1 addition & 0 deletions src/Navigation/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export enum PageNames {
Brand = "Brand",
Brands = "Brands",
FitPicDetail = "FitPicDetail",
Collection = "Collection",
FitPicConfirmation = "FitPicConfirmation",
ReferralView = "ReferralView",

Expand Down
3 changes: 2 additions & 1 deletion src/Notifications/NotificationsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Platform } from "react-native"
import gql from "graphql-tag"
import NotificationsContext from "./NotificationsContext"
import RNPusherPushNotifications from "react-native-pusher-push-notifications"
import { useQuery } from "react-apollo"
import { useQuery } from "@apollo/client"
import { useNavigation } from "@react-navigation/native"
import { getUserSession } from "App/utils/auth"

Expand All @@ -16,6 +16,7 @@ export const seasonsNotifInterest = "seasons-general-notifications"
export const GET_BEAMS_DATA = gql`
query BeamsData {
me {
id
user {
email
beamsToken
Expand Down
5 changes: 3 additions & 2 deletions src/Scenes/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import gql from "graphql-tag"
import { DateTime } from "luxon"
import { default as React, useEffect } from "react"
import { useQuery } from "react-apollo"
import { useQuery } from "@apollo/client"
import { Linking, Platform, ScrollView, StatusBar } from "react-native"
import * as Animatable from "react-native-animatable"
import Share from "react-native-share"
Expand All @@ -32,6 +32,7 @@ import { WaitlistedCTA, AuthorizedCTA } from "@seasons/eclipse"
export const GET_USER = gql`
query GetUser {
me {
id
customer {
id
status
Expand Down Expand Up @@ -84,7 +85,7 @@ export const GET_USER = gql`

export const Account = screenTrack()(({ navigation }) => {
const { authState, signOut } = useAuthContext()
const { data, refetch } = useQuery(GET_USER)
const { previousData, data = previousData, refetch } = useQuery(GET_USER)

const tracking = useTracking()

Expand Down
2 changes: 1 addition & 1 deletion src/Scenes/Account/Components/NotificationToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Text, Linking, AppState } from "react-native"
import { checkNotifications } from "react-native-permissions"
import { useNotificationsContext } from "App/Notifications/NotificationsContext"
import { useTracking, Schema } from "App/utils/track"
import { useMutation } from "react-apollo"
import { useMutation } from "@apollo/client"
import { usePopUpContext } from "App/Navigation/ErrorPopUp/PopUpContext"
import * as Sentry from "@sentry/react-native"
import { GetUser_me_customer_user_pushNotification } from "App/generated/getUser"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FlatList, Keyboard, KeyboardAvoidingView } from "react-native"
import { useSafeAreaInsets } from "react-native-safe-area-context"
import { StatePickerPopUp } from "./StatePickerPopup"
import gql from "graphql-tag"
import { useMutation } from "react-apollo"
import { useMutation } from "@apollo/client"
import { usePopUpContext } from "App/Navigation/ErrorPopUp/PopUpContext"
import { FadeBottom2 } from "Assets/svgs/FadeBottom2"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context"
import { areIndicesEqual, Index, Item, Section, sections } from "./Sections"

import gql from "graphql-tag"
import { useMutation } from "react-apollo"
import { useMutation } from "@apollo/client"
import { usePopUpContext } from "App/Navigation/ErrorPopUp/PopUpContext"

const UPDATE_STYLE_PREFERENCES = gql`
Expand Down
Loading

0 comments on commit c6f3795

Please sign in to comment.