mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
API to add recommended (popular) reads to a users library
This API is used in onboarding
This commit is contained in:
parent
8e30d793e0
commit
2b14d51ec6
10 changed files with 1486 additions and 0 deletions
|
|
@ -16,6 +16,24 @@ export type Scalars = {
|
|||
Date: any;
|
||||
};
|
||||
|
||||
export type AddPopularReadError = {
|
||||
__typename?: 'AddPopularReadError';
|
||||
errorCodes: Array<AddPopularReadErrorCode>;
|
||||
};
|
||||
|
||||
export enum AddPopularReadErrorCode {
|
||||
BadRequest = 'BAD_REQUEST',
|
||||
NotFound = 'NOT_FOUND',
|
||||
Unauthorized = 'UNAUTHORIZED'
|
||||
}
|
||||
|
||||
export type AddPopularReadResult = AddPopularReadError | AddPopularReadSuccess;
|
||||
|
||||
export type AddPopularReadSuccess = {
|
||||
__typename?: 'AddPopularReadSuccess';
|
||||
pageId: Scalars['String'];
|
||||
};
|
||||
|
||||
export type ArchiveLinkError = {
|
||||
__typename?: 'ArchiveLinkError';
|
||||
errorCodes: Array<ArchiveLinkErrorCode>;
|
||||
|
|
@ -783,6 +801,7 @@ export type MergeHighlightSuccess = {
|
|||
|
||||
export type Mutation = {
|
||||
__typename?: 'Mutation';
|
||||
addPopularRead: AddPopularReadResult;
|
||||
createArticle: CreateArticleResult;
|
||||
createArticleSavingRequest: CreateArticleSavingRequestResult;
|
||||
createHighlight: CreateHighlightResult;
|
||||
|
|
@ -832,6 +851,11 @@ export type Mutation = {
|
|||
};
|
||||
|
||||
|
||||
export type MutationAddPopularReadArgs = {
|
||||
name: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateArticleArgs = {
|
||||
input: CreateArticleInput;
|
||||
};
|
||||
|
|
@ -2115,6 +2139,10 @@ export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs
|
|||
|
||||
/** Mapping between all available schema types and the resolvers types */
|
||||
export type ResolversTypes = {
|
||||
AddPopularReadError: ResolverTypeWrapper<AddPopularReadError>;
|
||||
AddPopularReadErrorCode: AddPopularReadErrorCode;
|
||||
AddPopularReadResult: ResolversTypes['AddPopularReadError'] | ResolversTypes['AddPopularReadSuccess'];
|
||||
AddPopularReadSuccess: ResolverTypeWrapper<AddPopularReadSuccess>;
|
||||
ArchiveLinkError: ResolverTypeWrapper<ArchiveLinkError>;
|
||||
ArchiveLinkErrorCode: ArchiveLinkErrorCode;
|
||||
ArchiveLinkInput: ArchiveLinkInput;
|
||||
|
|
@ -2429,6 +2457,9 @@ export type ResolversTypes = {
|
|||
|
||||
/** Mapping between all available schema types and the resolvers parents */
|
||||
export type ResolversParentTypes = {
|
||||
AddPopularReadError: AddPopularReadError;
|
||||
AddPopularReadResult: ResolversParentTypes['AddPopularReadError'] | ResolversParentTypes['AddPopularReadSuccess'];
|
||||
AddPopularReadSuccess: AddPopularReadSuccess;
|
||||
ArchiveLinkError: ArchiveLinkError;
|
||||
ArchiveLinkInput: ArchiveLinkInput;
|
||||
ArchiveLinkResult: ResolversParentTypes['ArchiveLinkError'] | ResolversParentTypes['ArchiveLinkSuccess'];
|
||||
|
|
@ -2684,6 +2715,20 @@ export type SanitizeDirectiveArgs = {
|
|||
|
||||
export type SanitizeDirectiveResolver<Result, Parent, ContextType = ResolverContext, Args = SanitizeDirectiveArgs> = DirectiveResolverFn<Result, Parent, ContextType, Args>;
|
||||
|
||||
export type AddPopularReadErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['AddPopularReadError'] = ResolversParentTypes['AddPopularReadError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['AddPopularReadErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type AddPopularReadResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['AddPopularReadResult'] = ResolversParentTypes['AddPopularReadResult']> = {
|
||||
__resolveType: TypeResolveFn<'AddPopularReadError' | 'AddPopularReadSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type AddPopularReadSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['AddPopularReadSuccess'] = ResolversParentTypes['AddPopularReadSuccess']> = {
|
||||
pageId?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ArchiveLinkErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ArchiveLinkError'] = ResolversParentTypes['ArchiveLinkError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['ArchiveLinkErrorCode']>, ParentType, ContextType>;
|
||||
message?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
|
|
@ -3237,6 +3282,7 @@ export type MergeHighlightSuccessResolvers<ContextType = ResolverContext, Parent
|
|||
};
|
||||
|
||||
export type MutationResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = {
|
||||
addPopularRead?: Resolver<ResolversTypes['AddPopularReadResult'], ParentType, ContextType, RequireFields<MutationAddPopularReadArgs, 'name'>>;
|
||||
createArticle?: Resolver<ResolversTypes['CreateArticleResult'], ParentType, ContextType, RequireFields<MutationCreateArticleArgs, 'input'>>;
|
||||
createArticleSavingRequest?: Resolver<ResolversTypes['CreateArticleSavingRequestResult'], ParentType, ContextType, RequireFields<MutationCreateArticleSavingRequestArgs, 'input'>>;
|
||||
createHighlight?: Resolver<ResolversTypes['CreateHighlightResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightArgs, 'input'>>;
|
||||
|
|
@ -3878,6 +3924,9 @@ export type UserSuccessResolvers<ContextType = ResolverContext, ParentType exten
|
|||
};
|
||||
|
||||
export type Resolvers<ContextType = ResolverContext> = {
|
||||
AddPopularReadError?: AddPopularReadErrorResolvers<ContextType>;
|
||||
AddPopularReadResult?: AddPopularReadResultResolvers<ContextType>;
|
||||
AddPopularReadSuccess?: AddPopularReadSuccessResolvers<ContextType>;
|
||||
ArchiveLinkError?: ArchiveLinkErrorResolvers<ContextType>;
|
||||
ArchiveLinkResult?: ArchiveLinkResultResolvers<ContextType>;
|
||||
ArchiveLinkSuccess?: ArchiveLinkSuccessResolvers<ContextType>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
directive @sanitize(allowedTags: [String], maxLength: Int, pattern: String) on INPUT_FIELD_DEFINITION
|
||||
|
||||
type AddPopularReadError {
|
||||
errorCodes: [AddPopularReadErrorCode!]!
|
||||
}
|
||||
|
||||
enum AddPopularReadErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union AddPopularReadResult = AddPopularReadError | AddPopularReadSuccess
|
||||
|
||||
type AddPopularReadSuccess {
|
||||
pageId: String!
|
||||
}
|
||||
|
||||
type ArchiveLinkError {
|
||||
errorCodes: [ArchiveLinkErrorCode!]!
|
||||
message: String!
|
||||
|
|
@ -693,6 +709,7 @@ type MergeHighlightSuccess {
|
|||
}
|
||||
|
||||
type Mutation {
|
||||
addPopularRead(name: String!): AddPopularReadResult!
|
||||
createArticle(input: CreateArticleInput!): CreateArticleResult!
|
||||
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
|
||||
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ import {
|
|||
uploadFileRequestResolver,
|
||||
validateUsernameResolver,
|
||||
updatePageResolver,
|
||||
addPopularReadResolver,
|
||||
} from './index'
|
||||
import { getShareInfoForArticle } from '../datalayer/links/share_info'
|
||||
import {
|
||||
|
|
@ -149,6 +150,7 @@ export const functionResolvers = {
|
|||
unsubscribe: unsubscribeResolver,
|
||||
updatePage: updatePageResolver,
|
||||
subscribe: subscribeResolver,
|
||||
addPopularRead: addPopularReadResolver,
|
||||
},
|
||||
Query: {
|
||||
me: getMeUserResolver,
|
||||
|
|
@ -560,4 +562,5 @@ export const functionResolvers = {
|
|||
...resultResolveTypeResolver('UpdateLabel'),
|
||||
...resultResolveTypeResolver('UpdatePage'),
|
||||
...resultResolveTypeResolver('Subscribe'),
|
||||
...resultResolveTypeResolver('AddPopularRead'),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ export * from './user_device_tokens'
|
|||
export * from './labels'
|
||||
export * from './subscriptions'
|
||||
export * from './update'
|
||||
export * from './popular_reads'
|
||||
|
|
|
|||
45
packages/api/src/resolvers/popular_reads/index.ts
Normal file
45
packages/api/src/resolvers/popular_reads/index.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import {
|
||||
MutationAddPopularReadArgs,
|
||||
AddPopularReadError,
|
||||
AddPopularReadErrorCode,
|
||||
AddPopularReadSuccess,
|
||||
} from '../../generated/graphql'
|
||||
|
||||
import { authorized, userDataToUser } from '../../utils/helpers'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { addPopularRead } from '../../services/popular_reads'
|
||||
import { env } from '../../env'
|
||||
|
||||
export const addPopularReadResolver = authorized<
|
||||
AddPopularReadSuccess,
|
||||
AddPopularReadError,
|
||||
MutationAddPopularReadArgs
|
||||
>(async (_, { name }, ctx) => {
|
||||
console.log('************************ addPopularRead ************************')
|
||||
const {
|
||||
models,
|
||||
claims: { uid },
|
||||
} = ctx
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'popular_read_added',
|
||||
properties: {
|
||||
name: name,
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
|
||||
const user = userDataToUser(await models.user.get(uid))
|
||||
if (!user) {
|
||||
return { errorCodes: [AddPopularReadErrorCode.Unauthorized] }
|
||||
}
|
||||
|
||||
const pageId = await addPopularRead(uid, name)
|
||||
if (!pageId) {
|
||||
return { errorCodes: [AddPopularReadErrorCode.NotFound] }
|
||||
}
|
||||
|
||||
return {
|
||||
pageId,
|
||||
}
|
||||
})
|
||||
|
|
@ -1552,6 +1552,22 @@ const schema = gql`
|
|||
ALREADY_SUBSCRIBED
|
||||
}
|
||||
|
||||
union AddPopularReadResult = AddPopularReadSuccess | AddPopularReadError
|
||||
|
||||
type AddPopularReadSuccess {
|
||||
pageId: String!
|
||||
}
|
||||
|
||||
type AddPopularReadError {
|
||||
errorCodes: [AddPopularReadErrorCode!]!
|
||||
}
|
||||
|
||||
enum AddPopularReadErrorCode {
|
||||
UNAUTHORIZED
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
}
|
||||
|
||||
# Mutations
|
||||
type Mutation {
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
|
|
@ -1616,6 +1632,7 @@ const schema = gql`
|
|||
generateApiKey(input: GenerateApiKeyInput!): GenerateApiKeyResult!
|
||||
unsubscribe(name: String!): UnsubscribeResult!
|
||||
subscribe(name: String!): SubscribeResult!
|
||||
addPopularRead(name: String!): AddPopularReadResult!
|
||||
}
|
||||
|
||||
# FIXME: remove sort from feedArticles after all cached tabs are closed
|
||||
|
|
|
|||
108
packages/api/src/services/popular_reads.ts
Normal file
108
packages/api/src/services/popular_reads.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import { createPage } from '../elastic/pages'
|
||||
import { createPubSubClient } from '../datalayer/pubsub'
|
||||
import { ArticleSavingRequestStatus, Page, PageContext } from '../elastic/types'
|
||||
import { PageType } from '../generated/graphql'
|
||||
import { generateSlug, stringToHash } from '../utils/helpers'
|
||||
import { readFileSync } from 'fs';
|
||||
import path from 'path'
|
||||
|
||||
type PopularRead = {
|
||||
url: string
|
||||
title: string
|
||||
author: string
|
||||
description: string
|
||||
previewImage: string
|
||||
publishedAt: Date
|
||||
siteName: string
|
||||
|
||||
content: string
|
||||
originalHtml: string
|
||||
}
|
||||
|
||||
const popularRead = (key: string): PopularRead | undefined => {
|
||||
const metadata = popularReads.find((pr) => pr.key === key)
|
||||
if (!metadata) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
const content = readFileSync(path.resolve(__dirname, `popular_reads/${key}-content.html`), 'utf8')
|
||||
const originalHtml = readFileSync(path.resolve(__dirname, `./popular_reads/${key}-original.html`), 'utf8')
|
||||
if (!content || !originalHtml) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
...metadata,
|
||||
content,
|
||||
originalHtml,
|
||||
}
|
||||
}
|
||||
|
||||
export const addPopularRead = async (
|
||||
userId: string,
|
||||
name: string
|
||||
): Promise<string | undefined> => {
|
||||
const ctx: PageContext = {
|
||||
pubsub: createPubSubClient(),
|
||||
refresh: true,
|
||||
uid: userId,
|
||||
}
|
||||
|
||||
const pr = popularRead(name)
|
||||
if (!pr) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const saveTime = new Date()
|
||||
const slug = generateSlug(pr.title)
|
||||
|
||||
const articleToSave: Page = {
|
||||
id: '',
|
||||
slug: slug,
|
||||
userId: userId,
|
||||
content: pr.content,
|
||||
originalHtml: pr.originalHtml,
|
||||
description: pr.description,
|
||||
title: pr.title,
|
||||
author: pr.author,
|
||||
url: pr.url,
|
||||
pageType: PageType.Article,
|
||||
hash: stringToHash(pr.content),
|
||||
image: pr.previewImage,
|
||||
publishedAt: pr.publishedAt,
|
||||
savedAt: saveTime,
|
||||
createdAt: saveTime,
|
||||
siteName: pr.siteName,
|
||||
readingProgressPercent: 0,
|
||||
readingProgressAnchorIndex: 0,
|
||||
state: ArticleSavingRequestStatus.Succeeded,
|
||||
}
|
||||
|
||||
const pageId = await createPage(articleToSave, ctx)
|
||||
return pageId
|
||||
}
|
||||
|
||||
|
||||
const popularReads = [
|
||||
{
|
||||
key: 'omnivore_get_started',
|
||||
url: 'https://blog.omnivore.app/p/getting-started-with-omnivore',
|
||||
title: 'Getting Started with Omnivore',
|
||||
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',
|
||||
publishedAt: new Date('2021-10-13'),
|
||||
siteName: 'Omnivore Blog',
|
||||
},
|
||||
{
|
||||
key: 'omnivire_organize',
|
||||
url: 'https://blog.omnivore.app/p/organize-your-omnivore-library-with',
|
||||
title: 'Organize your Omnivore library with labels',
|
||||
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',
|
||||
publishedAt: new Date('2022-04-18'),
|
||||
siteName: 'Omnivore Blog',
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<DIV class="page" id="readability-page-1">
|
||||
<div>
|
||||
<h3> Learn the best ways to save links with Omnivore </h3>
|
||||
</div>
|
||||
<div dir="auto">
|
||||
<p> Omnivore is a home for everything you read. We keep it safe, organized, and easy to share. </p>
|
||||
<p> When you start using Omnivore, it is important to figure out the best way to save content to your library. </p>
|
||||
<h2>
|
||||
<strong>Saving from your iPhone</strong>
|
||||
</h2>
|
||||
<p> If you are using an iPhone or iPad, the best way to save links is by installing the iOS app. You can find the iOS app here: </p>
|
||||
<p>
|
||||
<a href="https://omnivore.app/install/ios" rel="">https://omnivore.app/install/ios</a>
|
||||
</p>
|
||||
<p> With the iOS Share extension installed, you can save links from Safari or any other app that supports sharing links. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif" width="320" height="523.75" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/b116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif","fullscreen":null,"imageSize":null,"height":419,"width":256,"resizeWidth":null,"bytes":275502,"alt":"Saving with the Omnivore iOS Share Extension","title":null,"type":"image/gif","href":null}" alt="Saving with the Omnivore iOS Share Extension" title="Saving with the Omnivore iOS Share Extension" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fb116ac39-34b8-4868-a2b0-b20c79f610c3_256x419.gif 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
<figcaption> Saving with the Omnivore iOS Share Extension </figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<p> When you first install the app, Omnivore might not show up in your list of share targets. To make sure Omnivore is easy to access, scroll to the far right, click More, and add Omnivore. </p>
|
||||
<h2> Saving from your Android Device </h2>
|
||||
<p> If you are using an Android device you can install the Omnivore Progressive Web App. After logging in to Omnivore in Chrome you should see an “Install Omnivore” option. Most Android versions display this at the bottom of the screen. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png" width="320" height="152" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png","fullscreen":null,"imageSize":null,"height":152,"width":320,"resizeWidth":null,"bytes":15668,"alt":null,"title":null,"type":null,"href":null}" alt="" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4255167b-bc82-4187-a043-3150cbbdc17d_320x152.png 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
</figure>
|
||||
</div>
|
||||
<p> After installing Omnivore as a Progressive Web App it will be displayed in your Sharing Menu on Chrome. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png" width="320" height="693" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/f382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png","fullscreen":null,"imageSize":null,"height":693,"width":320,"resizeWidth":null,"bytes":43062,"alt":null,"title":null,"type":null,"href":null}" alt="" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff382aca6-3fbf-4a0c-a69e-8270c1554e24_320x693.png 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
</figure>
|
||||
</div>
|
||||
<h2>
|
||||
<strong>Saving from your computer</strong>
|
||||
</h2>
|
||||
<p> If you are saving from a computer, you will need to install the Omnivore extension for the web browser(s) you use. </p>
|
||||
<p> The browser extensions are available here: </p>
|
||||
<ul>
|
||||
<li>
|
||||
<p> Chrome: <a href="https://omnivore.app/install/chrome" rel="">https://omnivore.app/install/chrome</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p> Edge: <a href="https://omnivore.app/install/edge" rel="">https://omnivore.app/install/edge</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p> Firefox: <a href="https://omnivore.app/install/firefox" rel="">https://omnivore.app/install/firefox</a>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p> Safari: https://omnivore.app/install/safari </p>
|
||||
</li>
|
||||
</ul>
|
||||
<p> With the browser extension(s) of your choice installed, you can tap the Omnivore button on any page to save your link. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,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">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,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 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,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 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,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 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,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 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,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" width="800" height="668" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/658efff4-341a-4720-8cf6-9b2bdbedfaa7_800x668.gif","fullscreen":null,"imageSize":null,"height":668,"width":800,"resizeWidth":null,"bytes":148745,"alt":"Saving with the Omnivore Browser Extension","title":null,"type":"image/gif","href":null}" alt="Saving with the Omnivore Browser Extension" title="Saving with the Omnivore Browser Extension" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,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 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,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 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,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 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,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 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
<figcaption> Saving with the Omnivore Browser Extension </figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<h2>
|
||||
<strong>Saving PDFs with the Mac App</strong>
|
||||
</h2>
|
||||
<p> https://omnivore.app/install/mac </p>
|
||||
<p> With the MacOS App installed you can upload PDFs from your computer to your Omnivore library by right-clicking and sharing to Omnivore. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png" width="1400" height="955" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png","fullscreen":null,"imageSize":null,"height":955,"width":1400,"resizeWidth":null,"bytes":297887,"alt":"Sharing a PDF with Omnivore","title":null,"type":"image/png","href":null}" alt="Sharing a PDF with Omnivore" title="Sharing a PDF with Omnivore" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F598e774d-1c20-43e3-bccf-be875f7b6616_1400x955.png 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
<figcaption> Sharing a PDF with Omnivore </figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<p> You can enable sharing from Finder on the Mac in the Extensions section of System Preferences. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif" width="960" height="709" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/e109c534-a502-49cb-a245-3deba005fe84_960x709.gif","fullscreen":null,"imageSize":null,"height":709,"width":960,"resizeWidth":null,"bytes":2973845,"alt":null,"title":null,"type":null,"href":null}" alt="" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe109c534-a502-49cb-a245-3deba005fe84_960x709.gif 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
</figure>
|
||||
</div>
|
||||
<h2> Using Omnivore </h2>
|
||||
<p> We created a quick tour of Omnivore to get your started with all the other features. This video demonstrates search, archiving, and keyboard commands in the library and sharing highlights from the reader. </p>
|
||||
<div>
|
||||
<figure>
|
||||
<a target="_blank" rel="nofollow" href="https://www.loom.com/share/a9afdd040dd349e28317430e1a178acc">
|
||||
<picture>
|
||||
<source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif" width="576" height="360" data-attrs="{"src":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif","fullscreen":null,"imageSize":null,"height":360,"width":576,"resizeWidth":null,"bytes":71790,"alt":"Screenshot of video demonstrating Omnivore","title":null,"type":"image/gif","href":"https://www.loom.com/share/a9afdd040dd349e28317430e1a178acc"}" alt="Screenshot of video demonstrating Omnivore" title="Screenshot of video demonstrating Omnivore" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F59cc33d5-9a9f-4e40-b4a3-c7a399cc293f_576x360.gif 1456w" sizes="100vw">
|
||||
</picture>
|
||||
</a>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</DIV>
|
||||
File diff suppressed because one or more lines are too long
61
packages/api/test/resolvers/popular_reads.test.ts
Normal file
61
packages/api/test/resolvers/popular_reads.test.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { createTestSubscription, createTestUser, deleteTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { Subscription } from '../../src/entity/subscription'
|
||||
import { expect } from 'chai'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getPageById, getPageByParam } from '../../src/elastic/pages'
|
||||
|
||||
describe('PopularReads API', () => {
|
||||
const username = 'fakeUser'
|
||||
|
||||
let user: User
|
||||
let authToken: string
|
||||
|
||||
const addPopularReadQuery = (readName: string) => {
|
||||
return `
|
||||
mutation {
|
||||
addPopularRead(name: "${readName}") {
|
||||
... on AddPopularReadSuccess {
|
||||
pageId
|
||||
}
|
||||
... on AddPopularReadError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
// create test user and login
|
||||
user = await createTestUser(username)
|
||||
const res = await request
|
||||
.post('/local/debug/fake-user-login')
|
||||
.send({ fakeEmail: user.email })
|
||||
|
||||
authToken = res.body.authToken
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(username)
|
||||
})
|
||||
|
||||
describe('addPopularRead', () => {
|
||||
it('should add a new article if the readName is valid', async () => {
|
||||
const readName = 'omnivore_get_started'
|
||||
const res = await graphqlRequest(addPopularReadQuery(readName), authToken).expect(200)
|
||||
expect(res.body.data.addPopularRead.pageId).to.be
|
||||
|
||||
const page = await getPageByParam({ userId: user.id, _id: res.body.data.addPopularRead.pageId })
|
||||
expect(page?.url).to.eq('https://blog.omnivore.app/p/getting-started-with-omnivore')
|
||||
})
|
||||
|
||||
it('responds status code 500 when invalid user', async () => {
|
||||
const invalidAuthToken = 'Fake token'
|
||||
const readName = 'omnivore_get_started'
|
||||
return graphqlRequest(addPopularReadQuery(readName), invalidAuthToken).expect(500)
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue