feat: offline detection
This commit is contained in:
16
src/App.js
16
src/App.js
@@ -18,6 +18,7 @@ import Register from "./components/screens/Register"
|
|||||||
import Start from "./components/screens/Start"
|
import Start from "./components/screens/Start"
|
||||||
import PrivateRoute from "./components/PrivateRoute"
|
import PrivateRoute from "./components/PrivateRoute"
|
||||||
|
|
||||||
|
import { OnlineContext } from "./components/context/online"
|
||||||
import { withAuthentication } from "./components/session"
|
import { withAuthentication } from "./components/session"
|
||||||
import { withFirebase } from "./components/firebase"
|
import { withFirebase } from "./components/firebase"
|
||||||
|
|
||||||
@@ -42,6 +43,17 @@ class App extends Component {
|
|||||||
new Date().getHours() >= 7 && new Date().getHours() <= 21
|
new Date().getHours() >= 7 && new Date().getHours() <= 21
|
||||||
? "LIGHT"
|
? "LIGHT"
|
||||||
: "DARK",
|
: "DARK",
|
||||||
|
online: navigator.onLine,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener('online', () => {
|
||||||
|
this.setState({ online: true })
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('offline', () => {
|
||||||
|
this.setState({ online: false })
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeTheme = () => {
|
onChangeTheme = () => {
|
||||||
@@ -69,13 +81,14 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedTheme, authUser } = this.state
|
const { selectedTheme, authUser, online } = this.state
|
||||||
const { authUser: propAuthUser } = this.props
|
const { authUser: propAuthUser } = this.props
|
||||||
const authed = !!propAuthUser || !!authUser
|
const authed = !!propAuthUser || !!authUser
|
||||||
|
|
||||||
const currentTheme = theme[selectedTheme]
|
const currentTheme = theme[selectedTheme]
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={currentTheme}>
|
<ThemeProvider theme={currentTheme}>
|
||||||
|
<OnlineContext.Provider value={online}>
|
||||||
<Router>
|
<Router>
|
||||||
<FullscreenLayout>
|
<FullscreenLayout>
|
||||||
<Navbar toggleTheme={this.onChangeTheme} />
|
<Navbar toggleTheme={this.onChangeTheme} />
|
||||||
@@ -106,6 +119,7 @@ class App extends Component {
|
|||||||
</RouteLayout>
|
</RouteLayout>
|
||||||
</FullscreenLayout>
|
</FullscreenLayout>
|
||||||
</Router>
|
</Router>
|
||||||
|
</OnlineContext.Provider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/components/context/online.js
Normal file
5
src/components/context/online.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export const OnlineContext = React.createContext({
|
||||||
|
online: navigator.onLine,
|
||||||
|
});
|
||||||
@@ -8,6 +8,7 @@ import { withRouter } from "react-router-dom"
|
|||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
import { withFirebase } from "../../firebase"
|
import { withFirebase } from "../../firebase"
|
||||||
import { withAuthentication } from "../../session"
|
import { withAuthentication } from "../../session"
|
||||||
|
import { OnlineContext } from "../../context/online"
|
||||||
import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns"
|
import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns"
|
||||||
import { BeatLoader } from "react-spinners"
|
import { BeatLoader } from "react-spinners"
|
||||||
|
|
||||||
@@ -23,6 +24,11 @@ const EntryHeading = styled.div`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: ${SIZES.medium};
|
margin-top: ${SIZES.medium};
|
||||||
`
|
`
|
||||||
|
const EntryInfo = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
`
|
||||||
const JournalHeading = styled.h2`
|
const JournalHeading = styled.h2`
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: ${SIZES.tiny};
|
font-size: ${SIZES.tiny};
|
||||||
@@ -37,6 +43,13 @@ const SavedMessaged = styled.div`
|
|||||||
font-size: ${SIZES.tiny};
|
font-size: ${SIZES.tiny};
|
||||||
user-select: none;
|
user-select: none;
|
||||||
`
|
`
|
||||||
|
const OfflineNotice = styled.div`
|
||||||
|
padding: 5px;
|
||||||
|
color: ${props => props.theme.colors.secondary};
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: ${props => props.theme.colors.tertiary};
|
||||||
|
border-radius: 3px;
|
||||||
|
`
|
||||||
const JournalEntryArea = styled.textarea`
|
const JournalEntryArea = styled.textarea`
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
flex-grow: 0.85;
|
flex-grow: 0.85;
|
||||||
@@ -95,6 +108,8 @@ class Day extends React.Component {
|
|||||||
timeout = 0
|
timeout = 0
|
||||||
retrievedFromServer = false
|
retrievedFromServer = false
|
||||||
|
|
||||||
|
static contextType = OnlineContext
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const {
|
||||||
history,
|
history,
|
||||||
@@ -137,6 +152,7 @@ class Day extends React.Component {
|
|||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.warn("entry not found in cache")
|
console.warn("entry not found in cache")
|
||||||
|
this.setState({ loading: false})
|
||||||
// for cache first, server second fetching, dangerous with potential overwriting of data
|
// for cache first, server second fetching, dangerous with potential overwriting of data
|
||||||
// docRef.get().then(doc => {
|
// docRef.get().then(doc => {
|
||||||
// if (doc.data()) {
|
// if (doc.data()) {
|
||||||
@@ -184,10 +200,7 @@ class Day extends React.Component {
|
|||||||
|
|
||||||
saveText = (text, year, month, day) => {
|
saveText = (text, year, month, day) => {
|
||||||
this.setState({ saving: true })
|
this.setState({ saving: true })
|
||||||
const {
|
const { firebase, authUser } = this.props
|
||||||
firebase,
|
|
||||||
authUser,
|
|
||||||
} = this.props
|
|
||||||
firebase.db
|
firebase.db
|
||||||
.collection("entries")
|
.collection("entries")
|
||||||
.doc(`${year}${month}${day}-${authUser.uid}`)
|
.doc(`${year}${month}${day}-${authUser.uid}`)
|
||||||
@@ -215,6 +228,7 @@ class Day extends React.Component {
|
|||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const online = this.context
|
||||||
const { text, loading, saving, lastSavedAt, lastEditedAt } = this.state
|
const { text, loading, saving, lastSavedAt, lastEditedAt } = this.state
|
||||||
const currentDay = new Date(year, month - 1, day)
|
const currentDay = new Date(year, month - 1, day)
|
||||||
if (!currentDay) return
|
if (!currentDay) return
|
||||||
@@ -222,7 +236,10 @@ class Day extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Prompt when={!hasSavedChanges} message="You have unsaved changes, are you sure you want to leave?" />
|
<Prompt
|
||||||
|
when={!hasSavedChanges}
|
||||||
|
message="You have unsaved changes, are you sure you want to leave?"
|
||||||
|
/>
|
||||||
<Seek
|
<Seek
|
||||||
title={format(currentDay, "YYYY MMM DD - dddd")}
|
title={format(currentDay, "YYYY MMM DD - dddd")}
|
||||||
prev={format(subDays(currentDay, 1), "/YYYY/MM/DD")}
|
prev={format(subDays(currentDay, 1), "/YYYY/MM/DD")}
|
||||||
@@ -231,6 +248,7 @@ class Day extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<EntryHeading>
|
<EntryHeading>
|
||||||
<JournalHeading>RECORD THOUGHTS ABOUT YOUR DAY</JournalHeading>
|
<JournalHeading>RECORD THOUGHTS ABOUT YOUR DAY</JournalHeading>
|
||||||
|
<EntryInfo>
|
||||||
<SavedMessaged>
|
<SavedMessaged>
|
||||||
{saving ? (
|
{saving ? (
|
||||||
<>
|
<>
|
||||||
@@ -249,6 +267,8 @@ class Day extends React.Component {
|
|||||||
"Unsaved changes"
|
"Unsaved changes"
|
||||||
)}
|
)}
|
||||||
</SavedMessaged>
|
</SavedMessaged>
|
||||||
|
{!online && <OfflineNotice>Offline</OfflineNotice>}
|
||||||
|
</EntryInfo>
|
||||||
</EntryHeading>
|
</EntryHeading>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div style={{ marginTop: 10 }}>
|
<div style={{ marginTop: 10 }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user