Improved offline handling

This commit is contained in:
Tom Moor
2018-06-07 21:35:40 -07:00
parent 21d887151d
commit f8cd3bf8c4
8 changed files with 50 additions and 48 deletions

View File

@@ -158,11 +158,7 @@ class Document extends BaseModel {
@action
view = async () => {
this.views++;
try {
await client.post('/views.create', { id: this.id });
} catch (e) {
this.ui.showToast('Document failed to record view');
}
await client.post('/views.create', { id: this.id });
};
@action

View File

@@ -32,6 +32,7 @@ import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
import Search from 'scenes/Search';
import Error404 from 'scenes/Error404';
import ErrorOffline from 'scenes/ErrorOffline';
const AUTOSAVE_INTERVAL = 3000;
const MARK_AS_VIEWED_AFTER = 3000;
@@ -245,7 +246,15 @@ class DocumentScene extends React.Component<Props> {
const isShare = match.params.shareId;
if (this.notFound) {
return isShare ? <Error404 /> : <Search notFound />;
return navigator.onLine ? (
isShare ? (
<Error404 />
) : (
<Search notFound />
)
) : (
<ErrorOffline />
);
}
return (

View File

@@ -2,13 +2,14 @@
import * as React from 'react';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
import Empty from 'components/Empty';
const Error404 = () => {
return (
<CenteredContent>
<PageTitle title="Not Found" />
<h1>Not Found</h1>
<p>We were unable to find the page youre looking for.</p>
<Empty>We were unable to find the page youre looking for.</Empty>
<p>
Go to <a href="/">homepage</a>.
</p>

View File

@@ -1,3 +0,0 @@
// @flow
import Error404 from './Error404';
export default Error404;

View File

@@ -0,0 +1,17 @@
// @flow
import * as React from 'react';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
import Empty from 'components/Empty';
const ErrorOffline = () => {
return (
<CenteredContent>
<PageTitle title="Offline" />
<h1>Offline</h1>
<Empty>We were unable to load the document while offline.</Empty>
</CenteredContent>
);
};
export default ErrorOffline;

View File

@@ -186,7 +186,7 @@ class Search extends React.Component<Props> {
{notFound && (
<div>
<h1>Not Found</h1>
<p>Were unable to find the page youre accessing.</p>
<Empty>We were unable to find the page youre looking for.</Empty>
</div>
)}
<ResultsWrapper pinToTop={this.pinToTop} column auto>

View File

@@ -196,8 +196,10 @@ class DocumentsStore extends BaseStore {
});
return document;
} catch (e) {
this.ui.showToast('Failed to load document');
} catch (_err) {
if (!options.prefetch && navigator.onLine) {
this.ui.showToast('Failed to load document');
}
} finally {
this.isFetching = false;
}

View File

@@ -16,7 +16,7 @@ class ApiClient {
this.userAgent = 'OutlineFrontend';
}
fetch = (
fetch = async (
path: string,
method: string,
data: ?Object,
@@ -45,9 +45,8 @@ class ApiClient {
headers.set('Authorization', `Bearer ${stores.auth.token}`);
}
// Construct request
// $FlowFixMe don't care much about this right now
const request = fetch(this.baseUrl + (modifiedPath || path), {
const response = await fetch(this.baseUrl + (modifiedPath || path), {
method,
body,
headers,
@@ -55,40 +54,21 @@ class ApiClient {
credentials: 'include',
});
// Handle request promises and return a new promise
return new Promise((resolve, reject) => {
request
.then(response => {
// Handle successful responses
if (response.status >= 200 && response.status < 300) {
return response;
}
if (response.status >= 200 && response.status < 300) {
return response.json();
}
// Handle 401, log out user
if (response.status === 401) {
stores.auth.logout();
return;
}
// Handle 401, log out user
if (response.status === 401) {
stores.auth.logout();
return;
}
// Handle failed responses
const error = {};
error.statusCode = response.status;
error.response = response;
throw error;
})
.then(response => {
return response && response.json();
})
.then(json => {
resolve(json);
})
.catch(error => {
error.response.json().then(json => {
error.error = json;
reject(error);
});
});
});
// Handle failed responses
const error = {};
error.statusCode = response.status;
error.response = response;
throw error;
};
get = (path: string, data: ?Object, options?: Object) => {