Skip to content

Commit

Permalink
Handle error when loading article (#105)
Browse files Browse the repository at this point in the history
* Handle error whern loading article

Show an error page if loading an article fail.
One way to test this is to use the search page
to list articles, then turn off your wifi
before trying to load one.

https://phabricator.wikimedia.org/T236897

* Add refresh option on the error page to retry loading the article.

* Show loading animation on refresh

Co-authored-by: Huei Tan <[email protected]>
  • Loading branch information
stephanebisson and hueitan committed Jan 28, 2020
1 parent c3d7064 commit 29c803a
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 6 deletions.
2 changes: 2 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"article-action-quickfacts": "Quick Facts",
"article-language-available": "Available in $1 {{PLURAL:$1|language|languages}}",
"article-loading-message": "Loading page...",
"article-error-message": "Unable to load article",
"app-title": "Wikipedia",
"app-subtitle": "The free encyclopedia",
"app-description": "With the free Wikipedia app, search and explore information from all over the world in 300+ languages.",
Expand Down Expand Up @@ -46,6 +47,7 @@
"softkey-back": "Back",
"softkey-skip": "Skip",
"softkey-get-started": "Get started",
"softkey-refresh": "Refresh",
"suggested-articles": "SUGGESTED ARTICLES",
"reference-title": "Reference [$1]",
"offline-message": "No internet connection ",
Expand Down
2 changes: 2 additions & 0 deletions i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"article-action-quickfacts": "The action button quick facts text on the first page of the article used to open the quick facts page and the label of the Quick facts item shown in the Menu page.",
"article-language-available": "The header title of the article language search page. The word \"available\" refers to the article.",
"article-loading-message": "The message when loading the article. Shown in the article page",
"article-error-message": "The message when an article cannot be loaded because the device is offline or for any reason.",
"app-title": "Title of the application. Shown in the app store and the app launcher.",
"app-subtitle": "Subtitle of the application. Shown in the app store.",
"app-description": "Description of the application. Shown in the app store. The word \"free\" is in the sense of \"zero dollars, you don't have pay\".",
Expand Down Expand Up @@ -45,6 +46,7 @@
"softkey-back": "Label of the back softkey",
"softkey-skip": "Label of the skip softkey",
"softkey-get-started": "Label of the get started softkey",
"softkey-refresh": "Label of the refresh softkey. Shown on the article error page.",
"reference-title": "Header of the reference preview popup.\n* $1 - Number of the current reference.",
"offline-message": "Message to be display at the top of the screen when there is no internet connection.",
"onboarding-0-title": "First onboarding title message when the user first time start the application.",
Expand Down
Binary file added images/article-error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions src/components/Article.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState, useRef, useEffect } from 'preact/hooks'
import {
ReferencePreview, ArticleToc, ArticleLanguage,
ArticleMenu, ArticleFooter, Loading, QuickFacts,
Gallery
Error, Gallery
} from 'components'
import {
useArticle, useI18n, useSoftkey,
Expand Down Expand Up @@ -95,12 +95,16 @@ const ArticleSection = ({
const ArticleInner = ({ lang, articleTitle, initialSubTitle }) => {
const i18n = useI18n()
const containerRef = useRef()
const article = useArticle(lang, articleTitle)
const [article, loadArticle] = useArticle(lang, articleTitle)

if (!article) {
return <Loading message={i18n.i18n('article-loading-message')} />
}

if (article.error) {
return <Error message={i18n.i18n('article-error-message')} onRefresh={loadArticle} />
}

const [subTitle, setSubTitle] = useState(initialSubTitle)
const [showTocPopup] = usePopup(ArticleToc, { mode: 'fullscreen' })
const [showQuickFactsPopup] = usePopup(QuickFacts, { mode: 'fullscreen' })
Expand Down
20 changes: 20 additions & 0 deletions src/components/Error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { h } from 'preact'
import { useSoftkey, useI18n } from 'hooks'

export const Error = ({ message, onRefresh }) => {
const i18n = useI18n()

useSoftkey('Error', {
center: i18n.i18n('softkey-refresh'),
onKeyCenter: onRefresh,
right: i18n.i18n('softkey-close'),
onKeyRight: () => history.back()
})

return (
<div class='error'>
<img src='images/article-error.png' />
<p class='message'>{message}</p>
</div>
)
}
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './ArticleMenu'
export * from './ArticlePreview'
export * from './ArticleToc'
export * from './ConfirmDialog'
export * from './Error'
export * from './Gallery'
export * from './Language'
export * from './ListView'
Expand Down
15 changes: 11 additions & 4 deletions src/hooks/useArticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { useI18n } from 'hooks'
import { getArticle, getArticleMedia, getSuggestedArticles } from 'api'

export const useArticle = (lang, title) => {
const [article, setArticle] = useState()
const [article, setArticle] = useState(null)
const i18n = useI18n()

useEffect(() => {
const loadArticle = () => {
setArticle(null)
Promise.all([getArticle(lang, title), getArticleMedia(lang, title), getSuggestedArticles(lang, title)])
.then(([article, media, suggestedArticles]) => {
const { sections, toc } = article
Expand All @@ -20,8 +21,14 @@ export const useArticle = (lang, title) => {
const tocWithFooter = toc.concat({ level: 1, line: i18n.i18n('toc-footer'), sectionIndex: sectionsWithFooter.length - 1 })

setArticle({ ...article, sections: sectionsWithFooter, toc: tocWithFooter, suggestedArticles, media })
}, error => {
setArticle({ error })
})
}

useEffect(() => {
loadArticle()
}, [lang, title])

return article
}
return [article, loadArticle]
}
14 changes: 14 additions & 0 deletions style/error.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.error {
height: @availableHeight;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;

p {
font-family: @textFont;
font-size: @bigFont;
text-align: center;
}
}
1 change: 1 addition & 0 deletions style/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// view style
@import './article';
@import './articlelanguage';
@import './error';
@import './footer';
@import './gallery';
@import './language';
Expand Down
1 change: 1 addition & 0 deletions style/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
@colorLight: #72777d;

@smallFont: 12px;
@bigFont: 17px;

0 comments on commit 29c803a

Please sign in to comment.