Merge pull request #2724 from omnivore-app/feat/web-improve-subscriptions-helper
Better actions for empty saved searches and improved thumbnails for onboarding articles
This commit is contained in:
@ -153,7 +153,7 @@ const popularReads = [
|
||||
author: 'The Omnivore Team',
|
||||
description: 'Get the most out of Omnivore by learning how to use it.',
|
||||
previewImage:
|
||||
'https://proxy-prod.omnivore-image-cache.app/88x88,sBp_gMyIp8Y4Mje8lzL39vzrBQg5m9KbprssrGjCbbHw/https://substackcdn.com/image/fetch/w_1200,h_600,c_limit,f_jpg,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F658efff4-341a-4720-8cf6-9b2bdbedfaa7_800x668.gif',
|
||||
'https://proxy-prod.omnivore-image-cache.app/320x320,sxQnqya1QNApB7ZAGPj9K20AU6sw0UAnjmAIy2ub8hUU/https://substackcdn.com/image/fetch/w_1200,h_600,c_fill,f_jpg,q_auto:good,fl_progressive:steep,g_auto/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F658efff4-341a-4720-8cf6-9b2bdbedfaa7_800x668.gif',
|
||||
publishedAt: new Date('2021-10-13'),
|
||||
siteName: 'Omnivore Blog',
|
||||
},
|
||||
@ -164,7 +164,7 @@ const popularReads = [
|
||||
author: 'Omnivore',
|
||||
description: 'Learn how to save articles on iOS.',
|
||||
previewImage:
|
||||
'https://proxy-prod.omnivore-image-cache.app/260x260,suM2fz_-6_1PDsQDursGPD2bQqnpgGH9Ymj-IVb5dUR4/https://substackcdn.com/image/youtube/w_728,c_limit/k6RkIqepAig',
|
||||
'https://proxy-prod.omnivore-image-cache.app/320x320,sWDfv7sARTIdAlx6Rw_6t-QwL3T9aniEJRa1-jVaglNg/https://substackcdn.com/image/youtube/w_728,c_limit/k6RkIqepAig',
|
||||
publishedAt: new Date('2021-10-19'),
|
||||
siteName: 'Omnivore Blog',
|
||||
},
|
||||
@ -175,7 +175,7 @@ const popularReads = [
|
||||
author: 'The Omnivore Team',
|
||||
description: 'Use labels to organize your Omnivore library.',
|
||||
previewImage:
|
||||
'https://proxy-prod.omnivore-image-cache.app/88x88,sSLRtT7zJbaNFEUbqDe9jbr3nloPsdjaqQXUqISk_x7E/https://substackcdn.com/image/fetch/w_1200,h_600,c_limit,f_jpg,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4ec9f3c-baef-464b-8d3a-0b8a384874d3_960x711.gif',
|
||||
'https://proxy-prod.omnivore-image-cache.app/320x320,sTgJ5Q0XIg_EHdmPWcxtXFmkjn8T6hkJt7S9ziClagYo/https://substackcdn.com/image/fetch/w_1200,h_600,c_fill,f_jpg,q_auto:good,fl_progressive:steep,g_auto/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf07af7-5cdb-4ecc-aace-1a46de3e9c58_1827x1090.png',
|
||||
publishedAt: new Date('2022-04-18'),
|
||||
siteName: 'Omnivore Blog',
|
||||
},
|
||||
@ -199,7 +199,7 @@ const popularReads = [
|
||||
description:
|
||||
'At the end of 2014 I received an email informing me that I had read over a million words in the ‘read it later’ app Pocket',
|
||||
previewImage:
|
||||
'https://proxy-prod.omnivore-image-cache.app/88x88,sVITWrJo3Wdi5LY3qSXX9aGytwKKteF8bth4z1MNz-PI/https://i0.wp.com/fortelabs.co/wp-content/uploads/2015/11/1rPXwIczUJRCE54v8FfAHGw.jpeg?fit=2000%2C844&ssl=1',
|
||||
'https://proxy-prod.omnivore-image-cache.app/320x320,sGN5R34M5z068QMXDZD32CQD6mCbxc47hWXm__JVUePE/https://fortelabs.com/wp-content/uploads/2015/11/1rPXwIczUJRCE54v8FfAHGw.jpeg',
|
||||
publishedAt: new Date('2022-01-24'),
|
||||
siteName: 'Forte Labs',
|
||||
},
|
||||
|
||||
@ -6,10 +6,14 @@ import { ReactNode } from 'react'
|
||||
import { Button } from './Button'
|
||||
import { CloseIcon } from './icons/CloseIcon'
|
||||
|
||||
export type SuggestionAction = {
|
||||
url: string
|
||||
text: string
|
||||
}
|
||||
|
||||
type SuggestionBoxProps = {
|
||||
helpMessage: string
|
||||
helpCTAText: string | undefined
|
||||
helpTarget: string | undefined
|
||||
suggestions: SuggestionAction[]
|
||||
|
||||
size?: 'large' | 'small'
|
||||
background?: string
|
||||
@ -90,28 +94,33 @@ export const SuggestionBox = (props: SuggestionBoxProps) => {
|
||||
</SpanBox>
|
||||
)}
|
||||
{props.helpMessage}
|
||||
{props.helpTarget && (
|
||||
<InternalOrExternalLink link={props.helpTarget}>
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
color: '$omnivoreCtaYellow',
|
||||
pt: '15px',
|
||||
gap: '2px',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
{props.suggestions.map((suggestion, idx) => {
|
||||
return (
|
||||
<InternalOrExternalLink
|
||||
key={`suggestions-${idx}`}
|
||||
link={suggestion.url}
|
||||
>
|
||||
<>{props.helpCTAText}</>
|
||||
<ArrowRightIcon
|
||||
size={25}
|
||||
color={theme.colors.omnivoreCtaYellow.toString()}
|
||||
/>
|
||||
</SpanBox>
|
||||
</InternalOrExternalLink>
|
||||
)}
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
color: '$omnivoreCtaYellow',
|
||||
pt: '15px',
|
||||
gap: '2px',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<>{suggestion.text}</>
|
||||
<ArrowRightIcon
|
||||
size={25}
|
||||
color={theme.colors.omnivoreCtaYellow.toString()}
|
||||
/>
|
||||
</SpanBox>
|
||||
</InternalOrExternalLink>
|
||||
)
|
||||
})}
|
||||
</VStack>
|
||||
</HStack>
|
||||
)
|
||||
|
||||
@ -1,15 +1,8 @@
|
||||
import Link from 'next/link'
|
||||
import { Book } from 'phosphor-react'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { Box } from '../../elements/LayoutPrimitives'
|
||||
import { useMemo } from 'react'
|
||||
import { searchQuery } from '../../../lib/networking/queries/search'
|
||||
import { LIBRARY_LEFT_MENU_WIDTH } from './LibraryFilterMenu'
|
||||
import { LayoutType } from './HomeFeedContainer'
|
||||
import { ArrowRightIcon } from '../../elements/icons/ArrowRightIcon'
|
||||
import { SuggestionBox } from '../../elements/SuggestionBox'
|
||||
import { SuggestionBox, SuggestionAction } from '../../elements/SuggestionBox'
|
||||
|
||||
type EmptyLibraryProps = {
|
||||
searchTerm: string | undefined
|
||||
@ -20,9 +13,14 @@ type EmptyLibraryProps = {
|
||||
|
||||
type MessageType =
|
||||
| 'inbox'
|
||||
| 'continue'
|
||||
| 'non-feed'
|
||||
| 'highlight'
|
||||
| 'unlabeled'
|
||||
| 'files'
|
||||
| 'archive'
|
||||
| 'feed'
|
||||
| 'subscription'
|
||||
| 'newsletter'
|
||||
| 'library'
|
||||
|
||||
@ -30,76 +28,29 @@ type HelpMessageProps = {
|
||||
type: MessageType
|
||||
}
|
||||
|
||||
const HelpMessage = (props: HelpMessageProps) => {
|
||||
switch (props.type) {
|
||||
case 'library':
|
||||
return (
|
||||
<>
|
||||
You can add a link or read more about Omnivore's{' '}
|
||||
<a
|
||||
href="https://docs.omnivore.app/using/search.html"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
advanced search
|
||||
</a>
|
||||
.
|
||||
</>
|
||||
)
|
||||
case 'feed':
|
||||
return (
|
||||
<>
|
||||
You can subscribe to RSS feeds using the{' '}
|
||||
<Link href="/settings/feeds" passHref>
|
||||
feeds page
|
||||
</Link>
|
||||
. Learn more about feeds at 's{' '}
|
||||
<a
|
||||
href="https://docs.omnivore.app/using/feeds.html"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
docs.omnivore.app/using/feeds.html
|
||||
</a>
|
||||
.
|
||||
</>
|
||||
)
|
||||
case 'newsletter':
|
||||
return (
|
||||
<>
|
||||
Create email addresses that can be used to subscribe to newsletters on
|
||||
the{' '}
|
||||
<Link href="/settings/emails" passHref>
|
||||
emails page
|
||||
</Link>
|
||||
. Learn more about reading newsletters in Omnivore at 's{' '}
|
||||
<a
|
||||
href="https://docs.omnivore.app/using/inbox.html"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
docs.omnivore.app/using/inbox.html
|
||||
</a>
|
||||
.
|
||||
</>
|
||||
)
|
||||
}
|
||||
return <></>
|
||||
}
|
||||
|
||||
export const ErrorBox = (props: HelpMessageProps) => {
|
||||
const errorTitle = useMemo(() => {
|
||||
switch (props.type) {
|
||||
case 'inbox':
|
||||
return 'Your inbox is empty.'
|
||||
return 'Your inbox is empty. The inbox will contain all your non-archived saved items.'
|
||||
case 'continue':
|
||||
return "No continue reading items. Continue Reading items are items you have started but haven't finished reading."
|
||||
case 'non-feed':
|
||||
return "No non-feed items found. Non-feed items are items you've add to the library using the mobile apps, browser extensions, or Add Link button. Not newsletter or feed items."
|
||||
case 'highlight':
|
||||
return 'No highlights found. Add highlights to your library by highlighting text in the reader view.'
|
||||
case 'unlabeled':
|
||||
return 'No unlabeled items found. Items without labels can be found here. Use this query to easily triage your library.'
|
||||
case 'archive':
|
||||
return 'You do not have any archived items.'
|
||||
case 'files':
|
||||
return 'No files found.'
|
||||
case 'feed':
|
||||
return 'You do not have any feed items matching this query.'
|
||||
case 'subscription':
|
||||
return 'You do not have any subscriptions.'
|
||||
case 'newsletter':
|
||||
return 'You do not have any newsletter item matching this query.'
|
||||
return 'You do not have any newsletter items matching this query.'
|
||||
}
|
||||
return 'No results found for this query.'
|
||||
}, [props.type])
|
||||
@ -129,65 +80,79 @@ export const ErrorBox = (props: HelpMessageProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
type SuggestionMessage = {
|
||||
message: string
|
||||
actions: SuggestionAction[]
|
||||
}
|
||||
|
||||
export const Suggestion = (props: HelpMessageProps) => {
|
||||
const helpMessage = useMemo(() => {
|
||||
const helpMessage = useMemo<SuggestionMessage>(() => {
|
||||
switch (props.type) {
|
||||
case 'feed':
|
||||
return ['Want to add an RSS or Atom Subscription?', 'Click Here']
|
||||
return {
|
||||
message: 'Want to add an RSS or Atom Subscription?',
|
||||
actions: [
|
||||
{ text: 'Add an RSS or Atom feed', url: '/settings/feeds' },
|
||||
],
|
||||
}
|
||||
case 'archive':
|
||||
return [
|
||||
'When you are done reading something archive it and it will be saved in Omnivore forever.',
|
||||
'Read the Docs',
|
||||
]
|
||||
return {
|
||||
message:
|
||||
'When you are done reading something archive it and it will be saved in Omnivore forever.',
|
||||
actions: [
|
||||
{
|
||||
text: 'Read the docs',
|
||||
url: 'https://docs.omnivore.app/using/saving',
|
||||
},
|
||||
],
|
||||
}
|
||||
case 'files':
|
||||
return [
|
||||
'Drag PDFs into the library to add them to your Omnivore account.',
|
||||
undefined,
|
||||
]
|
||||
return {
|
||||
message:
|
||||
'Drag PDFs into the library to add them to your Omnivore account.',
|
||||
actions: [],
|
||||
}
|
||||
case 'newsletter':
|
||||
return [
|
||||
'Create an Omnivore email address and subscribe to newsletters.',
|
||||
'Click Here',
|
||||
]
|
||||
return {
|
||||
message:
|
||||
'Create an Omnivore email address and subscribe to newsletters.',
|
||||
actions: [
|
||||
{
|
||||
text: 'Create an email address for newsletters',
|
||||
url: '/settings/emails',
|
||||
},
|
||||
],
|
||||
}
|
||||
case 'subscription':
|
||||
return {
|
||||
message:
|
||||
'Create an Omnivore email address and subscribe to newsletters or add a feed from the Feeds page.',
|
||||
actions: [
|
||||
{ text: 'Add an RSS or Atom feed', url: '/settings/feeds' },
|
||||
{
|
||||
text: 'Create an email address for newsletters',
|
||||
url: '/settings/emails',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
return [
|
||||
"Add a link or read more about Omnivore's Advanced Search.",
|
||||
'Read the Docs',
|
||||
]
|
||||
}, [props.type])
|
||||
|
||||
const helpTarget = useMemo(() => {
|
||||
switch (props.type) {
|
||||
case 'feed':
|
||||
return '/settings/feeds'
|
||||
case 'archive':
|
||||
case 'files':
|
||||
return undefined
|
||||
case 'archive':
|
||||
case 'inbox':
|
||||
return 'https://docs.omnivore.app/using/saving'
|
||||
case 'newsletter':
|
||||
return '/settings/emails'
|
||||
return {
|
||||
message: "Add a link or read more about Omnivore's Advanced Search.",
|
||||
actions: [
|
||||
{
|
||||
text: 'Read the Docs',
|
||||
url: 'https://docs.omnivore.app/using/search.html',
|
||||
},
|
||||
],
|
||||
}
|
||||
return 'https://docs.omnivore.app/'
|
||||
}, [props.type])
|
||||
|
||||
const helpTargetWindow = useMemo(() => {
|
||||
switch (props.type) {
|
||||
case 'archive':
|
||||
case 'inbox':
|
||||
return '_blank'
|
||||
}
|
||||
return undefined
|
||||
}, [props.type])
|
||||
|
||||
return (
|
||||
<>
|
||||
{helpMessage[0] ? (
|
||||
{helpMessage ? (
|
||||
<SuggestionBox
|
||||
helpMessage={helpMessage[0]}
|
||||
helpCTAText={helpMessage[1]}
|
||||
helpTarget={helpTarget}
|
||||
helpMessage={helpMessage.message}
|
||||
suggestions={helpMessage.actions}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
@ -200,14 +165,24 @@ export const EmptyLibrary = (props: EmptyLibraryProps) => {
|
||||
const type = useMemo<MessageType>(() => {
|
||||
if (props.searchTerm) {
|
||||
switch (props.searchTerm) {
|
||||
case 'in:archive':
|
||||
return 'archive'
|
||||
case 'in:inbox':
|
||||
return 'inbox'
|
||||
case 'in:inbox sort:read-desc is:unread':
|
||||
return 'continue'
|
||||
case 'in:library':
|
||||
return 'non-feed'
|
||||
case 'has:highlights mode:highlights':
|
||||
return 'highlight'
|
||||
case 'no:label':
|
||||
return 'unlabeled'
|
||||
case 'type:file':
|
||||
return 'files'
|
||||
case 'in:archive':
|
||||
return 'archive'
|
||||
case 'label:RSS':
|
||||
return 'feed'
|
||||
case 'in:subscription':
|
||||
return 'subscription'
|
||||
case 'label:Newsletter':
|
||||
return 'newsletter'
|
||||
}
|
||||
|
||||
@ -194,6 +194,7 @@ function Subscriptions(props: LibraryFilterMenuProps): JSX.Element {
|
||||
>
|
||||
{!collapsed ? (
|
||||
<>
|
||||
<FilterButton filterTerm="in:subscription" text="All" {...props} />
|
||||
<FilterButton filterTerm={`label:RSS`} text="Feeds" {...props} />
|
||||
<FilterButton
|
||||
filterTerm={`label:Newsletter`}
|
||||
|
||||
Reference in New Issue
Block a user