Skip to content

Commit

Permalink
Merge pull request #389 from gregrickaby/feature/3.0.1
Browse files Browse the repository at this point in the history
v3.0.1
  • Loading branch information
gregrickaby authored Oct 5, 2022
2 parents 8d80b75 + c56fc4b commit c6a1ed1
Show file tree
Hide file tree
Showing 17 changed files with 356 additions and 202 deletions.
81 changes: 61 additions & 20 deletions components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {createStyles} from '@mantine/core'
import {cleanIframe} from '~/lib/helpers'
import {Post} from '~/lib/types'

const useStyles = createStyles((theme) => ({
card: {
Expand All @@ -19,18 +19,19 @@ const useStyles = createStyles((theme) => ({
/**
* Card component.
*/
export default function Card(props) {
export default function Card(props: Post) {
const {classes} = useStyles()
return (
<div className={classes.card}>
{(() => {
switch (props?.type) {
switch (props?.post_hint) {
case 'image':
return (
<a href={props?.permalink} aria-label={props?.title}>
<a href={props?.permalink}>
<img
alt={props?.title}
className={classes.image}
data-hint="image"
height={props?.images?.height}
loading="lazy"
src={props?.images?.url}
Expand All @@ -43,23 +44,56 @@ export default function Card(props) {
<video
className={classes.video}
controls
loop
muted
crossOrigin="anonymous"
data-hint="hosted:video"
height={props?.media?.reddit_video?.height}
playsInline
src={props?.secure_media?.reddit_video?.fallback_url}
/>
poster={props?.images?.url}
preload="metadata"
width={props?.media?.reddit_video?.width}
>
<source
src={props?.media?.reddit_video?.hls_url}
type="application/vnd.apple.mpegURL"
/>
</video>
)
case 'rich:video':
return (
<a
aria-label={props?.title}
dangerouslySetInnerHTML={{
__html: cleanIframe({
html: props?.media?.oembed?.html
})
return props?.video_preview ? (
<video
className={classes.video}
controls
crossOrigin="anonymous"
data-hint="rich:video"
height={props?.video_preview?.height}
muted
playsInline
poster={props?.images?.url}
preload="metadata"
width={props?.video_preview?.width}
>
<source
src={props?.video_preview?.fallback_url}
type="video/mp4"
/>
</video>
) : (
<div
style={{
height: props?.secure_media_embed?.height,
width: props?.secure_media_embed?.width
}}
href={props?.url}
/>
>
<iframe
allow="fullscreen"
loading="lazy"
referrerPolicy="no-referrer"
sandbox="allow-scripts allow-same-origin allow-presentation"
src={props?.secure_media_embed?.media_domain_url}
style={{border: 'none', height: '100%', width: '100%'}}
title="iframe"
/>
</div>
)
case 'link':
// Search for .gifv....
Expand All @@ -68,11 +102,18 @@ export default function Card(props) {
<video
className={classes.video}
controls
loop
crossOrigin="anonymous"
data-hint="link"
muted
playsInline
src={props?.url.replace('.gifv', '.mp4')} // Replace .gifv with .mp4.
></video>
poster={props?.images?.url}
preload="metadata"
>
<source
src={props?.url.replace('.gifv', '.mp4')}
type="video/mp4"
/>
</video>
)
} else {
// No media? Return blank.
Expand Down
43 changes: 43 additions & 0 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {createStyles} from '@mantine/core'
import {IconBrandGithub} from '@tabler/icons'
import config from '~/lib/config'

const useStyles = createStyles((theme) => ({
footer: {
alignItems: 'center',
display: 'flex',
gap: theme.spacing.md,
justifyContent: 'center',
textAlign: 'center',

a: {
color: theme.colors.dark[0]
}
}
}))

/**
* Footer component.
*/
export default function Footer() {
const {classes} = useStyles()
return (
<footer className={classes.footer}>
<p>
website by{' '}
<a href={config.authorUrl} target="_blank" rel="noopener noreferrer">
{config.siteAuthor}
</a>
</p>
<p>
<a
href="https://github.com/gregrickaby/reddit-image-viewer"
target="_blank"
rel="noopener noreferrer"
>
<IconBrandGithub />
</a>
</p>
</footer>
)
}
31 changes: 31 additions & 0 deletions components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {createStyles} from '@mantine/core'
import config from '~/lib/config'

const useStyles = createStyles((theme) => ({
header: {
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
[`@media (max-width: ${theme.breakpoints.sm}px)`]: {
flexDirection: 'column',
textAlign: 'center'
}
},
title: {
fontSize: theme.fontSizes.xl,
margin: 0,
[`@media (max-width: ${theme.breakpoints.sm}px)`]: {
lineHeight: 1
}
}
}))

export default function Header() {
const {classes} = useStyles()
return (
<header className={classes.header}>
<h1 className={classes.title}>{config.siteTitle}</h1>
<p>{config.siteDescription}</p>
</header>
)
}
53 changes: 53 additions & 0 deletions components/Meta.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Head from 'next/head'
import config from '~/lib/config'

export default function Meta() {
return (
<Head>
<title>{config?.siteTitle}</title>
<meta name="description" content={config?.siteDescription} />

<meta httpEquiv="x-ua-compatible" content="ie=edge" />
<link rel="preconnect" href="//preview.redd.it" crossOrigin="anonymous" />
<link rel="preconnect" href="//v.redd.it" crossOrigin="anonymous" />
<link
rel="preconnect"
href="//external-preview.redd.it"
crossOrigin="anonymous"
/>
<link rel="preconnect" href="//i.imgur.com" crossOrigin="anonymous" />
<link
as="fetch"
rel="preload"
href="/api/reddit?sub=itookapicture&amp;sort=hot&amp;limit=24&amp;after="
crossOrigin="same-origin"
/>
<link rel="shortcut icon" href="/favicon/favicon.ico" />
<link rel="apple-touch-icon" href="/favicon/icon.png" />
<link rel="icon" href="/favicon/icon.png" sizes="192x192" />

<meta property="og:type" content="website" />
<meta property="og:url" content={config?.siteUrl} />
<meta property="og:title" content={config?.siteTitle} />
<meta property="og:description" content={config?.siteDescription} />
<meta
property="og:image"
content={`${config?.siteUrl}social-share.jpg`}
/>

<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={config?.siteUrl} />
<meta property="twitter:title" content={config?.siteTitle} />
<meta property="twitter:description" content={config?.siteDescription} />
<meta
property="twitter:image"
content={`${config?.siteUrl}social-share.jpg`}
/>

<meta
name="google-site-verification"
content={process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION}
/>
</Head>
)
}
7 changes: 4 additions & 3 deletions components/NoResults.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {Stack} from '@mantine/core'
import Image from 'next/future/image'
import notFound from '../public/not-found.webp'

Expand All @@ -6,12 +7,12 @@ import notFound from '../public/not-found.webp'
*/
export default function NoResults() {
return (
<>
<Stack align="center">
<p>
Either the Reddit API is down or something else is wrong. Please try
your search again.
</p>
<Image alt="404 not found" src={notFound} />
</>
<Image alt="404 not found" priority placeholder="blur" src={notFound} />
</Stack>
)
}
12 changes: 11 additions & 1 deletion components/Results.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import {Button, createStyles} from '@mantine/core'
import dynamic from 'next/dynamic'
import {useEffect, useState} from 'react'
import {useInView} from 'react-intersection-observer'
import Masonry from 'react-masonry-css'
import Card from '~/components/Card'
import {useRedditContext} from '~/components/RedditProvider'
import SkeletonWrapper from '~/components/SkeletonWrapper'
import {fetchPosts} from '~/lib/helpers'

const DynamicNoResults = dynamic(() => import('./NoResults'), {
ssr: false
})

const breakpointColumnsObj = {
default: 3,
766: 1
Expand Down Expand Up @@ -83,10 +89,14 @@ export default function Results() {
}
}, [inView]) // eslint-disable-line react-hooks/exhaustive-deps

if (loading || !posts) {
if (loading) {
return <SkeletonWrapper />
}

if (!posts) {
return <DynamicNoResults />
}

return (
<>
<Masonry
Expand Down
2 changes: 1 addition & 1 deletion components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function Search() {
const {setSubreddit} = useRedditContext()
const {classes} = useStyles()
const [value, setValue] = useState('')
const [debounced] = useDebouncedValue(value, 200)
const [debounced] = useDebouncedValue(value, 300)
const {data: results} = useSWR(`/api/search?term=${debounced}`, fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
Expand Down
47 changes: 47 additions & 0 deletions components/Settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
Button,
createStyles,
Group,
Modal,
Switch,
useMantineColorScheme
} from '@mantine/core'
import {IconSettings} from '@tabler/icons'
import {useState} from 'react'

const useStyles = createStyles(() => ({
settings: {}
}))

export default function Settings() {
const {classes} = useStyles()
const [opened, setOpened] = useState(false)
const {colorScheme, toggleColorScheme} = useMantineColorScheme()

return (
<>
<Modal onClose={() => setOpened(false)} opened={opened} title="Settings">
<Switch
aria-label="Toggle between light and dark theme."
label="Toggle Dark Theme (⌘+J)"
checked={colorScheme === 'dark'}
offLabel="OFF"
onChange={() => toggleColorScheme()}
onLabel="ON"
size="lg"
/>
</Modal>

<Group className={classes.settings}>
<Button
aria-label="open settings"
color="gray"
onClick={() => setOpened(true)}
variant="subtle"
>
<IconSettings />
</Button>
</Group>
</>
)
}
22 changes: 0 additions & 22 deletions lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,3 @@ export async function fetchPosts({
}
}
}

interface CleanIframeProps {
html: string
}

/**
* Replace the src attribute with a less terrible version.
*/
export function cleanIframe({html}: CleanIframeProps) {
// Grab the src URL.
const source = html.match(/(src="([^"]+)")/gi)

return `<iframe
${source}
allow="autoplay fullscreen"
loading="lazy"
referrerpolicy="no-referrer"
sandbox="allow-scripts allow-same-origin allow-presentation"
style="height: auto; width: 100%;"
title="iframe"
/>`
}
Loading

1 comment on commit c6a1ed1

@vercel
Copy link

@vercel vercel bot commented on c6a1ed1 Oct 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.