diff --git a/ui/public/manifest.json b/ui/public/manifest.json
index f7d8555be..6f3e25798 100755
--- a/ui/public/manifest.json
+++ b/ui/public/manifest.json
@@ -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",
diff --git a/ui/src/articles/AddArticlePage.tsx b/ui/src/articles/AddArticlePage.tsx
new file mode 100644
index 000000000..dedeb1891
--- /dev/null
+++ b/ui/src/articles/AddArticlePage.tsx
@@ -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 (
+
+ }>
+
+
+ )
+}
diff --git a/ui/src/articles/Routes.tsx b/ui/src/articles/Routes.tsx
index b12223184..caccd4878 100644
--- a/ui/src/articles/Routes.tsx
+++ b/ui/src/articles/Routes.tsx
@@ -1,10 +1,11 @@
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
@@ -12,6 +13,7 @@ type AllProps = RouteComponentProps<{}> & ConnectedReduxProps
export default ({match}: AllProps) => (
+
)
diff --git a/ui/src/articles/components/AddArticleForm.tsx b/ui/src/articles/components/AddArticleForm.tsx
index ea427d9f1..cdf1ff690 100644
--- a/ui/src/articles/components/AddArticleForm.tsx
+++ b/ui/src/articles/components/AddArticleForm.tsx
@@ -18,6 +18,7 @@ interface AddArticleFormFields {
}
type Props = {
+ value?: string
category?: Category
onSuccess: (article: Article) => void
onCancel: (e: any) => void
@@ -25,10 +26,10 @@ type Props = {
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(null)
- const [formState, { url }] = useFormState()
+ const [formState, { url }] = useFormState({url: value})
const addArticleMutation = useMutation(AddNewArticle)
const addArticle = async (form: AddArticleFormFields) => {
diff --git a/ui/src/common/helpers.tsx b/ui/src/common/helpers.tsx
index 21197a870..ce538b64c 100644
--- a/ui/src/common/helpers.tsx
+++ b/ui/src/common/helpers.tsx
@@ -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 {
Loading: () => ReactNode
Error: (err: ApolloError | Error) => ReactNode