Skip to content

Commit

Permalink
feat(ui): add Web Share Target support
Browse files Browse the repository at this point in the history
  • Loading branch information
ncarlier committed Apr 22, 2019
1 parent 6fa96cd commit ad4774a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 4 deletions.
8 changes: 8 additions & 0 deletions ui/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
"type": "image/png"
}
],
"share_target": {
"action": "/unread/add",
"params": {
"title": "title",
"text": "text",
"url": "url"
}
},
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
Expand Down
43 changes: 43 additions & 0 deletions ui/src/articles/AddArticlePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'
import { RouteComponentProps } from 'react-router-dom'

import Page from '../common/Page'
import { URLRegExp } from '../common/helpers'
import ButtonIcon from '../common/ButtonIcon'
import AddArticleForm from './components/AddArticleForm'

type AllProps = RouteComponentProps

export default ({ location, history }: AllProps) => {
const params = new URLSearchParams(location.search)

let value = ""
if (params.has('url')) {
value = params.get('url')!
} else if (params.has('text') || params.has('title')) {
const text = params.get('text') || params.get('title')!
if (URLRegExp.test(text)) {
value = text
} else {
const matches = text.match(/\bhttps?:\/\/\S+/gi)
if (matches && URLRegExp.test(matches[0])) {
value = matches[0]
}
}
}

const redirect = () => history.replace("/unread")

return (
<Page title="Add new article"
actions={
<ButtonIcon
to="/unread"
icon="arrow_back"
title="back to the list"
/>
}>
<AddArticleForm value={value} onCancel={redirect} onSuccess={redirect} />
</Page>
)
}
6 changes: 4 additions & 2 deletions ui/src/articles/Routes.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React from 'react'
import { RouteComponentProps, Route, Switch } from 'react-router-dom'

import { ConnectedReduxProps } from '../store'

import ArticlesPage from './ArticlesPage'
import ArticlePage from './ArticlePage'

import { ConnectedReduxProps } from '../store'
import AddArticlePage from './AddArticlePage'

// Combine both state + dispatch props - as well as any props we want to pass - in a union type.
type AllProps = RouteComponentProps<{}> & ConnectedReduxProps

export default ({match}: AllProps) => (
<Switch>
<Route exact path={match.path + '/'} component={ArticlesPage} />
<Route exact path={match.path + '/add'} component={AddArticlePage} />
<Route path={match.path + '/:id'} component={ArticlePage} />
</Switch>
)
5 changes: 3 additions & 2 deletions ui/src/articles/components/AddArticleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ interface AddArticleFormFields {
}

type Props = {
value?: string
category?: Category
onSuccess: (article: Article) => void
onCancel: (e: any) => void
}

type AllProps = Props

export default ({ category, onSuccess, onCancel }: AllProps) => {
export default ({ value, category, onSuccess, onCancel }: AllProps) => {
const [loading, setLoading] = useState(false)
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [formState, { url }] = useFormState<AddArticleFormFields>()
const [formState, { url }] = useFormState<AddArticleFormFields>({url: value})
const addArticleMutation = useMutation<AddNewArticleRequest>(AddNewArticle)

const addArticle = async (form: AddArticleFormFields) => {
Expand Down
8 changes: 8 additions & 0 deletions ui/src/common/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import { ApolloError } from "apollo-boost"
import { FormState } from "react-use-form-state"
import { API_BASE_URL } from "../constants";


export const URLRegExp = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i') // fragment locator

export interface GQLResponsePattern<T> {
Loading: () => ReactNode
Error: (err: ApolloError | Error) => ReactNode
Expand Down

0 comments on commit ad4774a

Please sign in to comment.