aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--frontend/public/favicon.png (renamed from frontend/public/icon.png)bin5751 -> 5751 bytes
-rw-r--r--frontend/public/index.html29
-rw-r--r--frontend/src/App.js55
-rw-r--r--frontend/src/components/NextHead.js16
-rw-r--r--frontend/src/http/resolvePaste.js69
-rw-r--r--frontend/src/index.js10
-rw-r--r--frontend/src/pages/[hash].js11
-rw-r--r--frontend/src/pages/_app.js26
-rw-r--r--frontend/src/pages/raw/[hash].js13
9 files changed, 90 insertions, 139 deletions
diff --git a/frontend/public/icon.png b/frontend/public/favicon.png
index 8585bd2..8585bd2 100644
--- a/frontend/public/icon.png
+++ b/frontend/public/favicon.png
Binary files differ
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