diff options
| -rw-r--r-- | frontend/public/favicon.png (renamed from frontend/public/icon.png) | bin | 5751 -> 5751 bytes | |||
| -rw-r--r-- | frontend/public/index.html | 29 | ||||
| -rw-r--r-- | frontend/src/App.js | 55 | ||||
| -rw-r--r-- | frontend/src/components/NextHead.js | 16 | ||||
| -rw-r--r-- | frontend/src/http/resolvePaste.js | 69 | ||||
| -rw-r--r-- | frontend/src/index.js | 10 | ||||
| -rw-r--r-- | frontend/src/pages/[hash].js | 11 | ||||
| -rw-r--r-- | frontend/src/pages/_app.js | 26 | ||||
| -rw-r--r-- | frontend/src/pages/raw/[hash].js | 13 |
9 files changed, 90 insertions, 139 deletions
diff --git a/frontend/public/icon.png b/frontend/public/favicon.png Binary files differindex 8585bd2..8585bd2 100644 --- a/frontend/public/icon.png +++ b/frontend/public/favicon.png diff --git a/frontend/public/index.html b/frontend/public/index.html deleted file mode 100644 index 8ca24a5..0000000 --- a/frontend/public/index.html +++ /dev/null @@ -1,29 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta name="theme-color" content="#ffffff" /> - <meta - name="ctrl-v" - content="a modern, open-source pastebin with latex and markdown rendering support" - /> - <link rel="icon" href="icon.png"> - <link rel="preconnect" href="https://fonts.gstatic.com"> - <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap" rel="stylesheet"> - <title>ctrl-v | a modern, open-source pastebin </title> - <!-- Global site tag (gtag.js) - Google Analytics --> - <script async src="https://www.googletagmanager.com/gtag/js?id=G-DE1TYY2F24"></script> - <script> - window.dataLayer = window.dataLayer || []; - function gtag() { dataLayer.push(arguments); } - gtag('js', new Date()); - - gtag('config', 'G-DE1TYY2F24'); - </script> - </head> - <body> - <noscript>You need to enable JavaScript to run this app.</noscript> - <div id="root"></div> - </body> -</html> diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index f00397f..0000000 --- a/frontend/src/App.js +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import NewPaste from './components/pages/NewPaste' -import ViewPaste from './components/pages/ViewPaste' -import styled from 'styled-components' -import { - BrowserRouter as Router, - Switch, - Route, - useParams -} from "react-router-dom"; -import Raw from './components/pages/Raw' -import ThemeProvider from './theme/ThemeProvider' -import GlobalStyle from './theme/GlobalStyle' -import {Watermark} from "./components/Watermark"; - - - -const GetPasteWithParam = () => { - let { hash } = useParams(); - return <ViewPaste hash = {hash} />; -} - -const GetRawWithParam = () => { - let { hash } = useParams(); - return <Raw hash={hash} />; -} - -const App = () => { - return ( - <ThemeProvider> - <GlobalStyle /> - <Router> - <Switch> - <Route path="/raw/:hash"><GetRawWithParam /></Route> - <Route> - <Watermark/> - <Main id="appElement"> - <Switch> - <Route path="/:hash"> - <GetPasteWithParam /> - </Route> - <Route path="/"> - <NewPaste /> - </Route> - </Switch> - </Main> - </Route> - </Switch> - </Router> - </ThemeProvider> - ); -} - - -export default App; diff --git a/frontend/src/components/NextHead.js b/frontend/src/components/NextHead.js new file mode 100644 index 0000000..1019f61 --- /dev/null +++ b/frontend/src/components/NextHead.js @@ -0,0 +1,16 @@ +import Head from 'next/head' + +const NextHead = ({data}) => { + const title = data.title || "untitled paste" + const description = `${data.content.slice(0, 100)}... expires: ${data.expiry}` + return (<Head> + <title>ctrl-v | {title}</title> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta name="twitter:title" content={title} /> + <meta name="twitter:description" content={description} /> + <meta name="description" content={description} /> + </Head>) +} + +export default NextHead
\ No newline at end of file diff --git a/frontend/src/http/resolvePaste.js b/frontend/src/http/resolvePaste.js index 8d40cbe..aa4f8b6 100644 --- a/frontend/src/http/resolvePaste.js +++ b/frontend/src/http/resolvePaste.js @@ -2,42 +2,45 @@ import {useEffect, useState} from 'react' import {fetchPaste, fmtDateStr} from './shared' import {LANGS} from "../components/renderers/Code"; -const resolvePaste = (id, password = "") => { - const response = { - data: { - title: '', - content: '', - language: LANGS.detect, - expiry: '', - }, - unauthorized: false, - error: '', - } - return fetchPaste(id, password) - .then(resp => { - const data = resp.data - response.data = { - ...data, - expiry: fmtDateStr(data.expiry) - } - return response - }) - .catch(error => { - const resp = error.response - if (!resp) { - response.error = 'network error' - return - } +export const defaultResponse = { + data: { + title: '', + content: '', + language: LANGS.detect, + expiry: '', + }, + unauthorized: false, + error: '', +} - if (resp.status === 401) { - response.error = 'unauthorized' - response.unauthorized = true - return - } +const resolvePaste = async (id, password = "") => { + const response = {...defaultResponse} + try { + return await fetchPaste(id, password) + .then(resp => { + const data = resp.data + response.data = { + ...data, + expiry: fmtDateStr(data.expiry) + } + return response + }) + } catch (err) { + const resp = err.response + if (!resp) { + response.error = 'network error' + return response + } - response.error = `${resp.status}: ${resp.data}` + if (resp.status === 401) { + response.error = 'unauthorized' + response.unauthorized = true return response - }) + } + + response.error = `${resp.status}: ${resp.data}` + return response + } } export default resolvePaste
\ No newline at end of file diff --git a/frontend/src/index.js b/frontend/src/index.js deleted file mode 100644 index 7173ce5..0000000 --- a/frontend/src/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -ReactDOM.render( - <React.StrictMode> - <App /> - </React.StrictMode>, - document.getElementById('root') -);
\ No newline at end of file diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js index 6d65f3e..f281621 100644 --- a/frontend/src/pages/[hash].js +++ b/frontend/src/pages/[hash].js @@ -7,27 +7,23 @@ import RenderDispatch from '../components/renderers/RenderDispatch' import {Watermark} from "../components/Watermark"; import { useRouter } from 'next/router' import resolvePaste from "../http/resolvePaste"; +import NextHead from "../components/NextHead"; export async function getServerSideProps(ctx) { const data = await resolvePaste(ctx.params.hash) - - // Pass data to the page via props return { props: { ...data } } } const ViewPaste = ({data, unauthorized, error}) => { const router = useRouter() const { hash } = router.query - const [clientData, setClientData] = useState(data); const [theme, setTheme] = useState('atom'); const [isRenderMode, setIsRenderMode] = useState(false); const [enteredPass, setEnteredPass] = useState(''); const [correctPass, setCorrectPass] = useState(!unauthorized); - + const [clientData, setClientData] = useState(data) const {content, language, expiry, title} = clientData; - - const getWithPassword = (password, errorCallback) => { resolvePaste(hash, password) .then(resp => { @@ -54,6 +50,7 @@ const ViewPaste = ({data, unauthorized, error}) => { return ( <div> + {!error && <NextHead data={data} />} <PasswordModal hasPass={unauthorized} validPass={correctPass} @@ -74,7 +71,7 @@ const ViewPaste = ({data, unauthorized, error}) => { toggleRenderCallback={() => setIsRenderMode(!isRenderMode)} isRenderMode={isRenderMode} onChange={(e) => setTheme(e.target.value)} - err={error} + err={unauthorized ? '' : error} /> <Watermark/> </div> diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js index e013c64..115f47f 100644 --- a/frontend/src/pages/_app.js +++ b/frontend/src/pages/_app.js @@ -2,6 +2,7 @@ import React from 'react' import ThemeProvider from "../theme/ThemeProvider"; import GlobalStyle from "../theme/GlobalStyle"; import styled from "styled-components"; +import Head from "next/head"; const Main = styled.div` margin-top: 10vh; @@ -11,6 +12,31 @@ const Main = styled.div` const App = ({ Component, pageProps }) => ( <ThemeProvider> <GlobalStyle /> + <Head> + <meta charSet="utf-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1"/> + <meta name="theme-color" content="#ffffff"/> + <meta + name="description" + content="a modern, open-source pastebin with latex and markdown rendering support" + /> + <link rel="icon" href="/favicon.png" /> + <link rel="preconnect" href="https://fonts.gstatic.com" /> + <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap" + rel="stylesheet" /> + <title>ctrl-v | a modern, open-source pastebin</title> + <script async src="https://www.googletagmanager.com/gtag/js?id=G-DE1TYY2F24" /> + <script + dangerouslySetInnerHTML={{ + __html: ` + window.dataLayer = window.dataLayer || []; + function gtag() {dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'G-DE1TYY2F24'); + ` + }} + /> + </Head> <Main id="appElement"> <Component {...pageProps} /> </Main> diff --git a/frontend/src/pages/raw/[hash].js b/frontend/src/pages/raw/[hash].js index a100b4b..3374eea 100644 --- a/frontend/src/pages/raw/[hash].js +++ b/frontend/src/pages/raw/[hash].js @@ -2,6 +2,7 @@ import React from 'react'; import resolvePaste from "../../http/resolvePaste"; import {CodeLike} from "../../components/Common/mixins"; import styled from 'styled-components' +import NextHead from "../../components/NextHead"; const RawText = styled.pre` ${CodeLike} @@ -10,15 +11,17 @@ const RawText = styled.pre` export async function getServerSideProps(ctx) { const data = await resolvePaste(ctx.params.hash) - - // Pass data to the page via props + console.log(data) return { props: { ...data } } } const Raw = ({error, data}) => { - return <RawText> - {data?.content || error} - </RawText> + return <> + {!error && <NextHead data={data} />} + <RawText> + {data?.content || error} + </RawText> + </> } export default Raw
\ No newline at end of file |