Skip to content

Commit

Permalink
Merge pull request #2332 from thematters/develop
Browse files Browse the repository at this point in the history
Release: v3.35.0
  • Loading branch information
robertu7 authored Nov 30, 2021
2 parents 186a909 + 71bf8ce commit 5899b3a
Show file tree
Hide file tree
Showing 14 changed files with 45,144 additions and 405 deletions.
45,290 changes: 44,970 additions & 320 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "matters-web",
"version": "3.34.0",
"version": "3.35.0",
"description": "codebase of Matters' website",
"sideEffects": false,
"author": "Matters <[email protected]>",
Expand Down
11 changes: 4 additions & 7 deletions src/common/gql/fragmentTypes.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
"name": "Node",
"possibleTypes": [
{ "name": "Article" },
{ "name": "Chapter" },
{ "name": "Topic" },
{ "name": "Tag" },
{ "name": "Circle" },
{ "name": "Comment" },
Expand All @@ -40,6 +42,7 @@
"name": "Connection",
"possibleTypes": [
{ "name": "ArticleConnection" },
{ "name": "TopicConnection" },
{ "name": "TagConnection" },
{ "name": "CircleConnection" },
{ "name": "MemberConnection" },
Expand All @@ -54,7 +57,6 @@
{ "name": "RecentSearchConnection" },
{ "name": "AppreciationConnection" },
{ "name": "FollowingActivityConnection" },
{ "name": "FolloweeDonatedArticleConnection" },
{ "name": "ResponseConnection" },
{ "name": "TransactionConnection" },
{ "name": "OAuthClientConnection" }
Expand All @@ -70,12 +72,7 @@
{ "name": "UserCreateCircleActivity" },
{ "name": "UserRecommendationActivity" },
{ "name": "ArticleRecommendationActivity" },
{ "name": "CircleRecommendationActivity" },
{ "name": "UserSubscribeCircleActivity" },
{ "name": "UserFollowUserActivity" },
{ "name": "UserDonateArticleActivity" },
{ "name": "UserBookmarkArticleActivity" },
{ "name": "UserCollectArticleActivity" }
{ "name": "CircleRecommendationActivity" }
]
},
{
Expand Down
75 changes: 40 additions & 35 deletions src/common/utils/resolvers/gatewayUrls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,42 @@ import { timeout } from '~/common/utils'

const TEST_HASH = 'Qmaisz6NMhDB51cCvNWa1GMS7LU1pAxdF4Ld6Ft9kZEP2a'
const PUBLIC_GATEWAYS: string[] = [
"https://matters-meson.net/api/cdn/10vbg9/ipfs/:hash",
'https://ipfs.io/ipfs/:hash',
'https://gateway.ipfs.io/ipfs/:hash',
"https://dweb.link/ipfs/:hash",
"https://crustwebsites.net/ipfs/:hash",
"https://gateway.originprotocol.com/ipfs/:hash",
'https://dweb.link/ipfs/:hash',
'https://crustwebsites.net/ipfs/:hash',
'https://gateway.originprotocol.com/ipfs/:hash',
'https://cloudflare-ipfs.com/ipfs/:hash',
"https://ipfs.telos.miami/ipfs/:hash",
"https://ipfs.fleek.co/ipfs/:hash",
"https://cf-ipfs.com/ipfs/:hash",
"https://ipfs.eth.aragon.network/ipfs/:hash",
"https://ipfs.kaleido.art/ipfs/:hash",
"https://gateway.pinata.cloud/ipfs/:hash",
"https://ipfs.tribecap.co/ipfs/:hash",
"https://ipfs.azurewebsites.net/ipfs/:hash",
"https://ipfs.kxv.io/ipfs/:hash",
"https://infura-ipfs.io/ipfs/:hash",
"https://ipfs.decoo.io/ipfs/:hash",
"https://ipfs.eternum.io/ipfs/:hash",
"https://hardbin.com/ipfs/:hash",
"https://jorropo.net/ipfs/:hash",
"https://ipfs.adatools.io/ipfs/:hash",
"https://ravencoinipfs-gateway.com/ipfs/:hash",
"https://robotizing.net/ipfs/:hash",
"https://hub.textile.io/ipfs/:hash",
"https://ipfs.infura.io/ipfs/:hash",
"https://ipfs.trusti.id/ipfs/:hash",
"https://ipfs.yt/ipfs/:hash",
"https://storry.tv/ipfs/:hash",
"https://astyanax.io/ipfs/:hash",
"https://ipfs.1-2.dev/ipfs/:hash",
"https://ipfs.mihir.ch/ipfs/:hash",
"https://10.via0.com/ipfs/:hash",
"https://dweb.eu.org/ipfs/:hash",
"https://permaweb.eu.org/ipfs/:hash",
"https://video.oneloveipfs.com/ipfs/:hash",
"https://ipfs.overpi.com/ipfs/:hash",
'https://ipfs.telos.miami/ipfs/:hash',
'https://ipfs.fleek.co/ipfs/:hash',
'https://cf-ipfs.com/ipfs/:hash',
'https://ipfs.eth.aragon.network/ipfs/:hash',
'https://ipfs.kaleido.art/ipfs/:hash',
'https://gateway.pinata.cloud/ipfs/:hash',
'https://ipfs.tribecap.co/ipfs/:hash',
'https://ipfs.azurewebsites.net/ipfs/:hash',
'https://ipfs.kxv.io/ipfs/:hash',
'https://infura-ipfs.io/ipfs/:hash',
'https://ipfs.decoo.io/ipfs/:hash',
'https://ipfs.eternum.io/ipfs/:hash',
'https://hardbin.com/ipfs/:hash',
'https://jorropo.net/ipfs/:hash',
'https://ipfs.adatools.io/ipfs/:hash',
'https://ravencoinipfs-gateway.com/ipfs/:hash',
'https://robotizing.net/ipfs/:hash',
'https://hub.textile.io/ipfs/:hash',
'https://ipfs.infura.io/ipfs/:hash',
'https://ipfs.trusti.id/ipfs/:hash',
'https://ipfs.yt/ipfs/:hash',
'https://storry.tv/ipfs/:hash',
'https://astyanax.io/ipfs/:hash',
'https://ipfs.1-2.dev/ipfs/:hash',
'https://ipfs.mihir.ch/ipfs/:hash',
'https://10.via0.com/ipfs/:hash',
'https://dweb.eu.org/ipfs/:hash',
'https://permaweb.eu.org/ipfs/:hash',
'https://video.oneloveipfs.com/ipfs/:hash',
'https://ipfs.overpi.com/ipfs/:hash',
]

// check accessbility for a given hash and gateway
Expand Down Expand Up @@ -75,7 +74,13 @@ const gatewayUrlsResolver = async () => {
checkGateway(TEST_HASH, url).then((alive: boolean) => ({ url, alive }))
)
)
return checkers.filter(({ alive }) => alive).map(({ url }) => url)

const gatwayUrls = checkers.filter(({ alive }) => alive).map(({ url }) => url)

// meson network use 302 redirect, so we have to push it in mannually
gatwayUrls.unshift('https://matters-meson.net/api/cdn/10vbg9/ipfs/:hash')

return gatwayUrls
}

export default gatewayUrlsResolver
8 changes: 5 additions & 3 deletions src/components/DraftDigest/Feed/DeleteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

import { ADD_TOAST } from '~/common/enums'

import { DraftContext } from '../../../views/Me/Drafts/context'
import { DraftsContext } from '../../../views/Me/Drafts'

import { DeleteButtonDraft } from './__generated__/DeleteButtonDraft'
import { DeleteDraft } from './__generated__/DeleteDraft'
Expand All @@ -37,12 +37,14 @@ const fragments = {

const DeleteButton = ({ draft }: DeleteButtonProps) => {
const { show, openDialog, closeDialog } = useDialogSwitch(false)
const { edges, setEdges } = useContext(DraftContext)
const [edges, setEdges] = useContext(DraftsContext)

const [deleteDraft] = useMutation<DeleteDraft>(DELETE_DRAFT, {
variables: { id: draft.id },
update: () => {
const filteredEdges = edges.filter(({ node }) => node.id !== draft.id)
const filteredEdges = (edges ?? []).filter(
({ node }) => node.id !== draft.id
)

setEdges(filteredEdges)
},
Expand Down
22 changes: 21 additions & 1 deletion src/components/Head/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,30 @@ export const Head: React.FC<HeadProps> = (props) => {
{props.jsonLdData && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(props.jsonLdData) }}
dangerouslySetInnerHTML={{
__html: sanitize(JSON.stringify(props.jsonLdData)),
}}
key="ld-json-data"
/>
)}
</NextHead>
)
}

// https://redux.js.org/usage/server-rendering/#security-considerations
// from https://github.com/yahoo/serialize-javascript/blob/main/index.js#L19-L31
// except the '/'
const ESCAPED_CHARS: Record<string, string> = {
'<': '\\u003C',
'>': '\\u003E',
// '/' : '\\u002F',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
}

function sanitize(str: string): string {
return str.replace(
/[<>\u2028\u2029]/g,
(unsafeChar) => ESCAPED_CHARS[unsafeChar] || ''
)
}
1 change: 1 addition & 0 deletions src/components/Hook/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './useCache'
export * from './useCarousel'
export * from './useDialogSwitch'
export * from './useEventListener'
Expand Down
65 changes: 65 additions & 0 deletions src/components/Hook/useCache.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
Context,
createContext,
Dispatch,
ReactNode,
SetStateAction,
useState,
} from 'react'

type CacheType<T> = [cache: T | null, setCache: Dispatch<SetStateAction<T>>]

/**
* This hook helps to resolve the issue(#2266) about fetch-policy set to `no-cache`.
*
* Usage:
*
* ```tsx
* export const cacheContext = createCacheContext();
*
* function Component() {
* const [cache, setCache, CacheProvider] = useCache<CACHE_TYPE>(initialCache, cacheContext)
*
* const { data } = useQuery(gql_schema, {
* fetchPolicy: 'no-cache',
* onCompleted: () => setCache(data.xxx)
* })
*
* return (
* <CacheProvider>
* ...
* <ChildComponent />
* </CacheProvider>
* )
* }
*
* function ChildComponent() {
* const [cache, setCache] = useContext(cacheContext)
*
* ...
* }
*
* ```
*/

export const createCacheContext = <T extends {}>() =>
createContext<CacheType<T>>([null, () => undefined])

export function useCache<T>(
initialCache: T,
CacheContext: Context<CacheType<T>>
): [
T,
Dispatch<SetStateAction<T>>,
({ children }: { children: ReactNode }) => JSX.Element
] {
const [cache, setCache] = useState<T>(initialCache)

const CacheProvider = ({ children }: { children: ReactNode }) => (
<CacheContext.Provider value={[cache, setCache]}>
{children}
</CacheContext.Provider>
)

return [cache, setCache, CacheProvider]
}
2 changes: 1 addition & 1 deletion src/views/ArticleDetail/CustomizedSummary/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import summaryStyles from '~/common/styles/utils/content.article.css'

interface CustomizedSummaryProps {
summary?: string
summary?: string | null
}

const CustomizedSummary = ({ summary }: CustomizedSummaryProps) => {
Expand Down
1 change: 1 addition & 0 deletions src/views/ArticleDetail/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const ARTICLE_TRANSLATION = gql`
translation(input: { language: $language }) {
content
title
summary
}
}
}
Expand Down
41 changes: 22 additions & 19 deletions src/views/ArticleDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,31 +173,32 @@ const ArticleDetail = () => {
const shouldTranslate = !!(language && language !== viewerLanguage)
const [getTranslation, { data: translationData, loading: translating }] =
useLazyQuery<ArticleTranslation>(ARTICLE_TRANSLATION)

const titleTranslation = translationData?.article?.translation?.title
const contentTranslation = translationData?.article?.translation?.content
const summaryTranslation = translationData?.article?.translation?.summary

const toggleTranslate = () => {
setTranslate(!translated)

if (!translated) {
return
}
getTranslation({ variables: { mediaHash, language: viewerLanguage } })

getTranslation({ variables: { mediaHash, language: viewerLanguage } })

window.dispatchEvent(
new CustomEvent(ADD_TOAST, {
detail: {
color: 'green',
content: (
<Translate
zh_hant="正在翻譯為繁體中文"
zh_hans="正在翻译为简体中文"
en="Translating to English"
/>
),
},
})
)
window.dispatchEvent(
new CustomEvent(ADD_TOAST, {
detail: {
color: 'green',
content: (
<Translate
zh_hant="正在翻譯為繁體中文"
zh_hans="正在翻译为简体中文"
en="Translating to English"
/>
),
},
})
)
}
}

// edit mode
Expand Down Expand Up @@ -390,7 +391,9 @@ const ArticleDetail = () => {
</section>

{article?.summaryCustomized && (
<CustomizedSummary summary={summary} />
<CustomizedSummary
summary={translated ? summaryTranslation : summary}
/>
)}

<Content
Expand Down
4 changes: 3 additions & 1 deletion src/views/Circle/Profile/AddCircleArticle/Dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ const AddCircleArticleDialog = ({
)
}

export default (props: AddCircleArticleDialogProps) => (
const DialogWrapper = (props: AddCircleArticleDialogProps) => (
<Dialog.Lazy mounted={<AddCircleArticleDialog {...props} />}>
{({ openDialog }) => <>{props.children({ openDialog })}</>}
</Dialog.Lazy>
)

export default DialogWrapper
11 changes: 0 additions & 11 deletions src/views/Me/Drafts/context.ts

This file was deleted.

Loading

0 comments on commit 5899b3a

Please sign in to comment.