Skip to content

Commit

Permalink
Finally got some Suspense stuff working.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisBrownie55 committed Dec 21, 2020
1 parent cf7070a commit 10e5c09
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 284 deletions.
2 changes: 1 addition & 1 deletion .eslintcache

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .idea/codestream.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 16 additions & 18 deletions src/components/CharacterCard.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import {useMachine} from '@xstate/react'
import {useUser, useStorage} from 'reactfire'
import {Link as RouterLink} from 'react-router-dom'

import {useUser} from '../shared/firebase.js'
import {createResource, fetchImageURL} from '../shared/resources'

import '../styles/character-card.css'
import {ImageLoadingMachine} from '../shared/machines'

export function CharacterCard({character}) {
/**
* @param {{resource: ResourceReader<string>, alt: string}} props
* @constructor
*/
function CharacterCardArt({resource, alt}) {
const imageURL = resource.read()
return <img className="CharacterCard__cover" src={imageURL} alt={alt} />
}

export function CharacterCard({userID, character}) {
const user = useUser()
const storage = useStorage()
const [current] = useMachine(
ImageLoadingMachine.withContext({
storage,
userID: user.uid,
fileID: character.files[0],
}),
)
const imageResource = createResource(fetchImageURL(userID, character.files[0]))

console.log('Character', character)
return (
<figure className="CharacterCard">
{/*TODO: show skeleton image*/}
{current.matches('fetching') ? <p>loading</p> : null}
{/*TODO: replace alt with alt from data*/}
{current.matches('loaded') ? (
<img className="CharacterCard__cover" src={current.context.imageURL} alt={`Art of "${character.name}"`} />
) : null}
<CharacterCardArt resource={imageResource} alt={`Art of "${character.name}"`} />

<figcaption className="CharacterCard__overlay">
<p className="CharacterCard__name">{character.name}</p>
<RouterLink to={`/character/${character.id}`} className="CharacterCard__view-button">
Expand Down
6 changes: 3 additions & 3 deletions src/components/profile-photo.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {useMachine} from '@xstate/react'
import {useUser} from 'reactfire'
import {useUser} from '../shared/firebase.js'
import {useEffect} from 'react'
import {FontIcon, ImageIcon, Spinner} from '@fluentui/react'
import {colors} from '../shared/theme'
import {gravatarMachine} from '../shared/machines'
import {colors} from '../shared/theme.js'
import {gravatarMachine} from '../shared/machines.js'

function Circle({children, as: Component = 'div', background = 'none', size, style = {}, ...props}) {
return (
Expand Down
40 changes: 19 additions & 21 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,25 @@ function UnauthenticatedRoute({as, ...props}) {
ReactDOM.render(
<StrictMode>
<BasicBoundary>
<FirebaseProvider>
<FirebaseAppProvider firebaseConfig={config}>
<Suspense
fallback={
<Center>
<Spinner label="Preparing everything as fast as we can..." />
</Center>
}
>
<TransitionRouter>
<PrivateRoute exact as={(props) => <Suspense fallback={<p>Test</p>}><Home {...props} /></Suspense>} path="/" />
<PrivateRoute exact as={NewCharacter} path="/new-character" />
<PrivateRoute exact as={Character} path="/character/:characterID" />
<Landing exact path="/landing" />
<UnauthenticatedRoute exact as={Login} path="/login" />
<UnauthenticatedRoute exact as={Register} path="/register" />
<NoRoute exact path="*" />
</TransitionRouter>
</Suspense>
</FirebaseAppProvider>
</FirebaseProvider>
<Suspense
fallback={
<Center>
<Spinner label="Preparing everything as fast as we can..." />
</Center>
}
>
<FirebaseProvider>
<TransitionRouter>
<PrivateRoute exact as={Home} path="/" />
<PrivateRoute exact as={NewCharacter} path="/new-character" />
<PrivateRoute exact as={Character} path="/character/:characterID" />
<Landing exact path="/landing" />
<UnauthenticatedRoute exact as={Login} path="/login" />
<UnauthenticatedRoute exact as={Register} path="/register" />
<NoRoute exact path="*" />
</TransitionRouter>
</FirebaseProvider>
</Suspense>
</BasicBoundary>
</StrictMode>,
document.getElementById('root'),
Expand Down
12 changes: 5 additions & 7 deletions src/pages/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import {useState} from 'react'

import {DefaultButton, Link, MessageBar, MessageBarType, PrimaryButton, Stack, Text, TextField} from '@fluentui/react'
import {Link as RouterLink} from 'react-router-dom'
import * as firebase from 'firebase'
import {Center} from '../components/center'
import {Notifications} from '../components/notifications'
import {Center} from '../components/center.js'
import {Notifications} from '../components/notifications.js'
import {motion} from 'framer-motion'
import {transitions} from '../shared/config'
import {transitions} from '../shared/config.js'
import {firestore, auth, provider as googleProvider} from '../shared/firebase.js'

const googleProvider = new firebase.auth.GoogleAuthProvider()
const initialStatus = {type: 'idle', data: null}

const pageData = {
Expand Down Expand Up @@ -53,7 +52,7 @@ const pageData = {
user.updateProfile({
displayName: name,
})
firebase.firestore().collection('users').doc(user.uid).set({
firestore.collection('users').doc(user.uid).set({
characters: {},
})
})
Expand Down Expand Up @@ -85,7 +84,6 @@ const buttonVariants = {
}

function AuthenticationPage({type}) {
const auth = useAuth()
const [status, setStatus] = useState(initialStatus)

function resetStatus() {
Expand Down
13 changes: 7 additions & 6 deletions src/pages/character.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import {useMemo} from 'react'
import {useParams, useHistory} from 'react-router-dom'

import xss from 'xss'
import marked from 'marked'
import {motion} from 'framer-motion'
import {Text} from '@fluentui/react'
import {useMachine, useService} from '@xstate/react'
import {useParams, useHistory} from 'react-router-dom'
import {useFirestore, useFirestoreDoc, useStorage, useUser} from 'reactfire'
import {motion} from 'framer-motion'

import {colors} from '../shared/theme'
import {ActionButton} from '../components/action-button'
import xss from 'xss'
import marked from 'marked'
import {useMachine, useService} from '@xstate/react'
import {plainSlideshowMachine} from '../shared/machines'

function CharacterSlideshow({service}) {
const [state, send] = useService(service)
console.log(state.value)

switch (state.value) {
case 'fetching':
Expand Down
127 changes: 78 additions & 49 deletions src/pages/home.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,52 @@
import {useAuth, useFirestore, useFirestoreDoc} from 'reactfire'
import {Suspense} from 'react'

import {useHistory} from 'react-router-dom'
import {motion} from 'framer-motion'
import {Text} from '@fluentui/react'
import 'wicg-inert'
import '../styles/profile-menu.css'
import {ProfileMenu, ProfileMenuItem} from '../components/profile-menu'
import {
auth,
clearFirestoreCache,
createDocumentResource,
firestore,
useDocumentResource,
useUser,
} from '../shared/firebase'
import {colors} from '../shared/theme'
import {Text, Spinner} from '@fluentui/react'

import {Center} from '../components/center'
import {ActionButton} from '../components/action-button'
import {useHistory} from 'react-router-dom'
import {CharacterCard} from '../components/CharacterCard'
import {useEffect, useMemo, Suspense} from 'react'

let ref = firestore.collection('users').doc('qyn462H3paOebIjHGqyXlIRJrfl1')
let resource = createDocumentResource(ref)

export function Home() {
const user = useUser()
const ref = firestore.collection('users').doc(user.uid)
const resource = createDocumentResource(ref)
return (
<Suspense fallback={<p>Getting user characters</p>}>
<HomePage documentRef={ref} resource={resource} />
</Suspense>
)
}
import {ProfileMenu, ProfileMenuItem} from '../components/profile-menu'

function HomePage({documentRef, resource}) {
const user = useUser()
import {colors} from '../shared/theme'
import {auth, firestore, useUser} from '../shared/firebase.js'
import {createDocumentResource, useDocumentResource} from '../shared/resources.js'

const history = useHistory()
function openNewCharacterPage() {
history.push('/new-character')
}
import '../styles/profile-menu.css'
import 'wicg-inert'

function signOut() {
auth.signOut().then(() => {
history.push('/login')
})
}
/**
* @typedef {{
* characterID: string,
* files: [string],
* name: string,
* story: string
* }} Character
* @typedef {{characters: [Character]}} UserData
*/

const document = useDocumentResource(documentRef, resource)
console.log(document)
const {characters} = document
let posts = []
for (const character of characters) posts.push(<CharacterCard character={character} />)
/**
* Renders a list of `<CharacterCard>`'s from a document and a resource.
* @param {{
* documentRef: DocumentReference<UserData>,
* resource: ResourceReader<UserData>
* }} props
* @returns {JSX.Element|[JSX.Element]}
* @constructor
*/
function CharacterCardList({userID, documentRef, resource}) {
const {characters} = useDocumentResource(documentRef, resource)

if (!posts.length)
if (characters.length > 0) {
// Render all the Character Cards.
const characterCards = []
for (const character of characters) characterCards.push(<CharacterCard userID={userID} character={character} />)
return characterCards
} else {
// Inform the user of how to create a character.
// TODO: Add alt for pride-drawing.svg
posts = (
return (
<div
style={{
width: '100%',
Expand All @@ -71,6 +63,31 @@ function HomePage({documentRef, resource}) {
</Text>
</div>
)
}
}

/**
* Home page
* @returns {JSX.Element}
* @constructor
*/
export function Home() {
const user = useUser()

/** @type {DocumentReference<UserData>} */
const ref = firestore.collection('users').doc(user.uid)
const resource = createDocumentResource(ref)

const history = useHistory()
function openNewCharacterPage() {
history.push('/new-character')
}

function signOut() {
auth.signOut().then(() => {
history.push('/login')
})
}

return (
<motion.div layout style={{height: '100%', display: 'flex', flexDirection: 'column'}}>
Expand All @@ -85,7 +102,19 @@ function HomePage({documentRef, resource}) {
<ProfileMenuItem onClick={signOut}>Sign Out</ProfileMenuItem>
</ProfileMenu>
</header>
<main style={{flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center'}}>{posts}</main>

<main style={{flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
<Suspense
fallback={
<Center>
<Spinner label="Loading your characters..." />
</Center>
}
>
<CharacterCardList userID={user.uid} documentRef={ref} resource={resource} />
</Suspense>
</main>

<section style={{position: 'fixed', bottom: 0, left: 0, padding: 10}}>
<ActionButton variant="round" iconName="Add" onClick={openNewCharacterPage}>
New
Expand Down
Loading

0 comments on commit 10e5c09

Please sign in to comment.