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:
Jackson Harper
2023-09-04 18:43:45 +08:00
committed by GitHub
4 changed files with 128 additions and 143 deletions

View File

@ -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',
},

View File

@ -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>
)

View File

@ -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&apos;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 &apos;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 &apos;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'
}

View File

@ -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`}