mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Update GQL, fetch wordsCount
This commit is contained in:
parent
adfa67f896
commit
2ff12a70ad
18 changed files with 746 additions and 40 deletions
|
|
@ -40,6 +40,7 @@ fragment ArticleFields on Article {
|
|||
readAt
|
||||
updatedAt
|
||||
content
|
||||
wordsCount
|
||||
}
|
||||
|
||||
fragment HighlightFields on Highlight {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ query Search($after: String, $first: Int, $query: String) {
|
|||
name
|
||||
color
|
||||
}
|
||||
highlights {
|
||||
id
|
||||
type
|
||||
}
|
||||
pageId
|
||||
shortId
|
||||
quote
|
||||
|
|
@ -36,6 +40,7 @@ query Search($after: String, $first: Int, $query: String) {
|
|||
readAt
|
||||
savedAt
|
||||
updatedAt
|
||||
wordsCount
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ query UpdatesSince($after: String, $first: Int, $since: Date!) {
|
|||
name
|
||||
color
|
||||
}
|
||||
highlights {
|
||||
id
|
||||
type
|
||||
}
|
||||
pageId
|
||||
shortId
|
||||
quote
|
||||
|
|
@ -39,6 +43,7 @@ query UpdatesSince($after: String, $first: Int, $since: Date!) {
|
|||
savedAt
|
||||
updatedAt
|
||||
language
|
||||
wordsCount
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
directive @sanitize(allowedTags: [String], maxLength: Int, pattern: String) on INPUT_FIELD_DEFINITION
|
||||
directive @sanitize(allowedTags: [String], maxLength: Int, minLength: Int, pattern: String) on INPUT_FIELD_DEFINITION
|
||||
|
||||
type AddPopularReadError {
|
||||
errorCodes: [AddPopularReadErrorCode!]!
|
||||
|
|
@ -86,6 +86,8 @@ type Article {
|
|||
readAt: Date
|
||||
readingProgressAnchorIndex: Int!
|
||||
readingProgressPercent: Float!
|
||||
readingProgressTopPercent: Float
|
||||
recommendations: [Recommendation!]
|
||||
savedAt: Date!
|
||||
savedByViewer: Boolean
|
||||
shareInfo: LinkShareInfo
|
||||
|
|
@ -101,6 +103,7 @@ type Article {
|
|||
updatedAt: Date!
|
||||
uploadFileId: ID
|
||||
url: String!
|
||||
wordsCount: Int
|
||||
}
|
||||
|
||||
type ArticleEdge {
|
||||
|
|
@ -132,6 +135,7 @@ type ArticleSavingRequest {
|
|||
slug: String!
|
||||
status: ArticleSavingRequestStatus!
|
||||
updatedAt: Date!
|
||||
url: String!
|
||||
user: User!
|
||||
userId: ID! @deprecated(reason: "userId has been replaced with user")
|
||||
}
|
||||
|
|
@ -141,6 +145,7 @@ type ArticleSavingRequestError {
|
|||
}
|
||||
|
||||
enum ArticleSavingRequestErrorCode {
|
||||
BAD_DATA
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
|
@ -148,6 +153,7 @@ enum ArticleSavingRequestErrorCode {
|
|||
union ArticleSavingRequestResult = ArticleSavingRequestError | ArticleSavingRequestSuccess
|
||||
|
||||
enum ArticleSavingRequestStatus {
|
||||
ARCHIVED
|
||||
DELETED
|
||||
FAILED
|
||||
PROCESSING
|
||||
|
|
@ -177,7 +183,27 @@ type ArticlesSuccess {
|
|||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type BulkActionError {
|
||||
errorCodes: [BulkActionErrorCode!]!
|
||||
}
|
||||
|
||||
enum BulkActionErrorCode {
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union BulkActionResult = BulkActionError | BulkActionSuccess
|
||||
|
||||
type BulkActionSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
enum BulkActionType {
|
||||
ARCHIVE
|
||||
DELETE
|
||||
}
|
||||
|
||||
enum ContentReader {
|
||||
EPUB
|
||||
PDF
|
||||
WEB
|
||||
}
|
||||
|
|
@ -198,9 +224,11 @@ enum CreateArticleErrorCode {
|
|||
|
||||
input CreateArticleInput {
|
||||
articleSavingRequestId: ID
|
||||
labels: [CreateLabelInput!]
|
||||
preparedDocument: PreparedDocumentInput
|
||||
skipParsing: Boolean
|
||||
source: String
|
||||
state: ArticleSavingRequestStatus
|
||||
uploadFileId: ID
|
||||
url: String!
|
||||
}
|
||||
|
|
@ -232,6 +260,31 @@ type CreateArticleSuccess {
|
|||
user: User!
|
||||
}
|
||||
|
||||
type CreateGroupError {
|
||||
errorCodes: [CreateGroupErrorCode!]!
|
||||
}
|
||||
|
||||
enum CreateGroupErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input CreateGroupInput {
|
||||
description: String
|
||||
expiresInDays: Int
|
||||
maxMembers: Int
|
||||
name: String!
|
||||
onlyAdminCanPost: Boolean
|
||||
onlyAdminCanSeeMembers: Boolean
|
||||
topics: [String!]
|
||||
}
|
||||
|
||||
union CreateGroupResult = CreateGroupError | CreateGroupSuccess
|
||||
|
||||
type CreateGroupSuccess {
|
||||
group: RecommendationGroup!
|
||||
}
|
||||
|
||||
type CreateHighlightError {
|
||||
errorCodes: [CreateHighlightErrorCode!]!
|
||||
}
|
||||
|
|
@ -247,13 +300,17 @@ enum CreateHighlightErrorCode {
|
|||
input CreateHighlightInput {
|
||||
annotation: String
|
||||
articleId: ID!
|
||||
highlightPositionAnchorIndex: Int
|
||||
highlightPositionPercent: Float
|
||||
html: String
|
||||
id: ID!
|
||||
patch: String!
|
||||
patch: String
|
||||
prefix: String
|
||||
quote: String!
|
||||
quote: String
|
||||
sharedAt: Date
|
||||
shortId: String!
|
||||
suffix: String
|
||||
type: HighlightType
|
||||
}
|
||||
|
||||
type CreateHighlightReplyError {
|
||||
|
|
@ -296,7 +353,7 @@ enum CreateLabelErrorCode {
|
|||
}
|
||||
|
||||
input CreateLabelInput {
|
||||
color: String!
|
||||
color: String
|
||||
description: String
|
||||
name: String!
|
||||
}
|
||||
|
|
@ -388,6 +445,22 @@ type DeleteAccountSuccess {
|
|||
userID: ID!
|
||||
}
|
||||
|
||||
type DeleteFilterError {
|
||||
errorCodes: [DeleteFilterErrorCode!]!
|
||||
}
|
||||
|
||||
enum DeleteFilterErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union DeleteFilterResult = DeleteFilterError | DeleteFilterSuccess
|
||||
|
||||
type DeleteFilterSuccess {
|
||||
filter: Filter!
|
||||
}
|
||||
|
||||
type DeleteHighlightError {
|
||||
errorCodes: [DeleteHighlightErrorCode!]!
|
||||
}
|
||||
|
|
@ -500,6 +573,22 @@ type DeleteReminderSuccess {
|
|||
reminder: Reminder!
|
||||
}
|
||||
|
||||
type DeleteRuleError {
|
||||
errorCodes: [DeleteRuleErrorCode!]!
|
||||
}
|
||||
|
||||
enum DeleteRuleErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union DeleteRuleResult = DeleteRuleError | DeleteRuleSuccess
|
||||
|
||||
type DeleteRuleSuccess {
|
||||
rule: Rule!
|
||||
}
|
||||
|
||||
type DeleteWebhookError {
|
||||
errorCodes: [DeleteWebhookErrorCode!]!
|
||||
}
|
||||
|
|
@ -522,6 +611,31 @@ type DeviceToken {
|
|||
token: String!
|
||||
}
|
||||
|
||||
type DeviceTokensError {
|
||||
errorCodes: [DeviceTokensErrorCode!]!
|
||||
}
|
||||
|
||||
enum DeviceTokensErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union DeviceTokensResult = DeviceTokensError | DeviceTokensSuccess
|
||||
|
||||
type DeviceTokensSuccess {
|
||||
deviceTokens: [DeviceToken!]!
|
||||
}
|
||||
|
||||
type Feature {
|
||||
createdAt: Date!
|
||||
expiresAt: Date
|
||||
grantedAt: Date
|
||||
id: ID!
|
||||
name: String!
|
||||
token: String!
|
||||
updatedAt: Date!
|
||||
}
|
||||
|
||||
type FeedArticle {
|
||||
annotationsCount: Int
|
||||
article: Article!
|
||||
|
|
@ -555,6 +669,31 @@ type FeedArticlesSuccess {
|
|||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type Filter {
|
||||
createdAt: Date!
|
||||
description: String
|
||||
filter: String!
|
||||
id: ID!
|
||||
name: String!
|
||||
position: Int!
|
||||
updatedAt: Date!
|
||||
}
|
||||
|
||||
type FiltersError {
|
||||
errorCodes: [FiltersErrorCode!]!
|
||||
}
|
||||
|
||||
enum FiltersErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union FiltersResult = FiltersError | FiltersSuccess
|
||||
|
||||
type FiltersSuccess {
|
||||
filters: [Filter!]!
|
||||
}
|
||||
|
||||
type GenerateApiKeyError {
|
||||
errorCodes: [GenerateApiKeyErrorCode!]!
|
||||
}
|
||||
|
|
@ -644,19 +783,39 @@ type GoogleSignupSuccess {
|
|||
me: User!
|
||||
}
|
||||
|
||||
type GroupsError {
|
||||
errorCodes: [GroupsErrorCode!]!
|
||||
}
|
||||
|
||||
enum GroupsErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union GroupsResult = GroupsError | GroupsSuccess
|
||||
|
||||
type GroupsSuccess {
|
||||
groups: [RecommendationGroup!]!
|
||||
}
|
||||
|
||||
type Highlight {
|
||||
annotation: String
|
||||
createdAt: Date!
|
||||
createdByMe: Boolean!
|
||||
highlightPositionAnchorIndex: Int
|
||||
highlightPositionPercent: Float
|
||||
html: String
|
||||
id: ID!
|
||||
patch: String!
|
||||
labels: [Label!]
|
||||
patch: String
|
||||
prefix: String
|
||||
quote: String!
|
||||
quote: String
|
||||
reactions: [Reaction!]!
|
||||
replies: [HighlightReply!]!
|
||||
sharedAt: Date
|
||||
shortId: String!
|
||||
suffix: String
|
||||
type: HighlightType!
|
||||
updatedAt: Date!
|
||||
user: User!
|
||||
}
|
||||
|
|
@ -674,17 +833,40 @@ type HighlightStats {
|
|||
highlightCount: Int!
|
||||
}
|
||||
|
||||
enum HighlightType {
|
||||
HIGHLIGHT
|
||||
NOTE
|
||||
REDACTION
|
||||
}
|
||||
|
||||
type ImportFromIntegrationError {
|
||||
errorCodes: [ImportFromIntegrationErrorCode!]!
|
||||
}
|
||||
|
||||
enum ImportFromIntegrationErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union ImportFromIntegrationResult = ImportFromIntegrationError | ImportFromIntegrationSuccess
|
||||
|
||||
type ImportFromIntegrationSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Integration {
|
||||
createdAt: Date!
|
||||
enabled: Boolean!
|
||||
id: ID!
|
||||
name: String!
|
||||
token: String!
|
||||
type: IntegrationType!
|
||||
updatedAt: Date!
|
||||
}
|
||||
|
||||
enum IntegrationType {
|
||||
READWISE
|
||||
EXPORT
|
||||
IMPORT
|
||||
}
|
||||
|
||||
type IntegrationsError {
|
||||
|
|
@ -702,6 +884,22 @@ type IntegrationsSuccess {
|
|||
integrations: [Integration!]!
|
||||
}
|
||||
|
||||
type JoinGroupError {
|
||||
errorCodes: [JoinGroupErrorCode!]!
|
||||
}
|
||||
|
||||
enum JoinGroupErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union JoinGroupResult = JoinGroupError | JoinGroupSuccess
|
||||
|
||||
type JoinGroupSuccess {
|
||||
group: RecommendationGroup!
|
||||
}
|
||||
|
||||
type Label {
|
||||
color: String!
|
||||
createdAt: Date
|
||||
|
|
@ -727,6 +925,22 @@ type LabelsSuccess {
|
|||
labels: [Label!]!
|
||||
}
|
||||
|
||||
type LeaveGroupError {
|
||||
errorCodes: [LeaveGroupErrorCode!]!
|
||||
}
|
||||
|
||||
enum LeaveGroupErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union LeaveGroupResult = LeaveGroupError | LeaveGroupSuccess
|
||||
|
||||
type LeaveGroupSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Link {
|
||||
highlightStats: HighlightStats!
|
||||
id: ID!
|
||||
|
|
@ -782,6 +996,22 @@ type LoginSuccess {
|
|||
me: User!
|
||||
}
|
||||
|
||||
type MarkEmailAsItemError {
|
||||
errorCodes: [MarkEmailAsItemErrorCode!]!
|
||||
}
|
||||
|
||||
enum MarkEmailAsItemErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union MarkEmailAsItemResult = MarkEmailAsItemError | MarkEmailAsItemSuccess
|
||||
|
||||
type MarkEmailAsItemSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type MergeHighlightError {
|
||||
errorCodes: [MergeHighlightErrorCode!]!
|
||||
}
|
||||
|
|
@ -797,6 +1027,9 @@ enum MergeHighlightErrorCode {
|
|||
input MergeHighlightInput {
|
||||
annotation: String
|
||||
articleId: ID!
|
||||
highlightPositionAnchorIndex: Int
|
||||
highlightPositionPercent: Float
|
||||
html: String
|
||||
id: ID!
|
||||
overlapHighlightIdList: [String!]!
|
||||
patch: String!
|
||||
|
|
@ -813,6 +1046,27 @@ type MergeHighlightSuccess {
|
|||
overlapHighlightIdList: [String!]!
|
||||
}
|
||||
|
||||
type MoveFilterError {
|
||||
errorCodes: [MoveFilterErrorCode!]!
|
||||
}
|
||||
|
||||
enum MoveFilterErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input MoveFilterInput {
|
||||
afterFilterId: ID
|
||||
filterId: ID!
|
||||
}
|
||||
|
||||
union MoveFilterResult = MoveFilterError | MoveFilterSuccess
|
||||
|
||||
type MoveFilterSuccess {
|
||||
filter: Filter!
|
||||
}
|
||||
|
||||
type MoveLabelError {
|
||||
errorCodes: [MoveLabelErrorCode!]!
|
||||
}
|
||||
|
|
@ -836,8 +1090,10 @@ type MoveLabelSuccess {
|
|||
|
||||
type Mutation {
|
||||
addPopularRead(name: String!): AddPopularReadResult!
|
||||
bulkAction(action: BulkActionType!, query: String): BulkActionResult!
|
||||
createArticle(input: CreateArticleInput!): CreateArticleResult!
|
||||
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
|
||||
createGroup(input: CreateGroupInput!): CreateGroupResult!
|
||||
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
|
||||
createHighlightReply(input: CreateHighlightReplyInput!): CreateHighlightReplyResult!
|
||||
createLabel(input: CreateLabelInput!): CreateLabelResult!
|
||||
|
|
@ -845,6 +1101,7 @@ type Mutation {
|
|||
createReaction(input: CreateReactionInput!): CreateReactionResult!
|
||||
createReminder(input: CreateReminderInput!): CreateReminderResult!
|
||||
deleteAccount(userID: ID!): DeleteAccountResult!
|
||||
deleteFilter(id: ID!): DeleteFilterResult!
|
||||
deleteHighlight(highlightId: ID!): DeleteHighlightResult!
|
||||
deleteHighlightReply(highlightReplyId: ID!): DeleteHighlightReplyResult!
|
||||
deleteIntegration(id: ID!): DeleteIntegrationResult!
|
||||
|
|
@ -852,17 +1109,27 @@ type Mutation {
|
|||
deleteNewsletterEmail(newsletterEmailId: ID!): DeleteNewsletterEmailResult!
|
||||
deleteReaction(id: ID!): DeleteReactionResult!
|
||||
deleteReminder(id: ID!): DeleteReminderResult!
|
||||
deleteRule(id: ID!): DeleteRuleResult!
|
||||
deleteWebhook(id: ID!): DeleteWebhookResult!
|
||||
generateApiKey(input: GenerateApiKeyInput!): GenerateApiKeyResult!
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
googleSignup(input: GoogleSignupInput!): GoogleSignupResult!
|
||||
importFromIntegration(integrationId: ID!): ImportFromIntegrationResult!
|
||||
joinGroup(inviteCode: String!): JoinGroupResult!
|
||||
leaveGroup(groupId: ID!): LeaveGroupResult!
|
||||
logOut: LogOutResult!
|
||||
markEmailAsItem(recentEmailId: ID!): MarkEmailAsItemResult!
|
||||
mergeHighlight(input: MergeHighlightInput!): MergeHighlightResult!
|
||||
moveFilter(input: MoveFilterInput!): MoveFilterResult!
|
||||
moveLabel(input: MoveLabelInput!): MoveLabelResult!
|
||||
optInFeature(input: OptInFeatureInput!): OptInFeatureResult!
|
||||
recommend(input: RecommendInput!): RecommendResult!
|
||||
recommendHighlights(input: RecommendHighlightsInput!): RecommendHighlightsResult!
|
||||
reportItem(input: ReportItemInput!): ReportItemResult!
|
||||
revokeApiKey(id: ID!): RevokeApiKeyResult!
|
||||
saveArticleReadingProgress(input: SaveArticleReadingProgressInput!): SaveArticleReadingProgressResult!
|
||||
saveFile(input: SaveFileInput!): SaveResult!
|
||||
saveFilter(input: SaveFilterInput!): SaveFilterResult!
|
||||
savePage(input: SavePageInput!): SaveResult!
|
||||
saveUrl(input: SaveUrlInput!): SaveResult!
|
||||
setBookmarkArticle(input: SetBookmarkArticleInput!): SetBookmarkArticleResult!
|
||||
|
|
@ -872,6 +1139,7 @@ type Mutation {
|
|||
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
||||
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
||||
setLinkArchived(input: ArchiveLinkInput!): ArchiveLinkResult!
|
||||
setRule(input: SetRuleInput!): SetRuleResult!
|
||||
setShareArticle(input: SetShareArticleInput!): SetShareArticleResult!
|
||||
setShareHighlight(input: SetShareHighlightInput!): SetShareHighlightResult!
|
||||
setUserPersonalization(input: SetUserPersonalizationInput!): SetUserPersonalizationResult!
|
||||
|
|
@ -888,12 +1156,15 @@ type Mutation {
|
|||
updateUser(input: UpdateUserInput!): UpdateUserResult!
|
||||
updateUserProfile(input: UpdateUserProfileInput!): UpdateUserProfileResult!
|
||||
uploadFileRequest(input: UploadFileRequestInput!): UploadFileRequestResult!
|
||||
uploadImportFile(contentType: String!, type: UploadImportFileType!): UploadImportFileResult!
|
||||
}
|
||||
|
||||
type NewsletterEmail {
|
||||
address: String!
|
||||
confirmationCode: String
|
||||
createdAt: Date!
|
||||
id: ID!
|
||||
subscriptionCount: Int!
|
||||
}
|
||||
|
||||
type NewsletterEmailsError {
|
||||
|
|
@ -911,6 +1182,25 @@ type NewsletterEmailsSuccess {
|
|||
newsletterEmails: [NewsletterEmail!]!
|
||||
}
|
||||
|
||||
type OptInFeatureError {
|
||||
errorCodes: [OptInFeatureErrorCode!]!
|
||||
}
|
||||
|
||||
enum OptInFeatureErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
}
|
||||
|
||||
input OptInFeatureInput {
|
||||
name: String!
|
||||
}
|
||||
|
||||
union OptInFeatureResult = OptInFeatureError | OptInFeatureSuccess
|
||||
|
||||
type OptInFeatureSuccess {
|
||||
feature: Feature!
|
||||
}
|
||||
|
||||
type Page {
|
||||
author: String
|
||||
createdAt: Date!
|
||||
|
|
@ -951,11 +1241,29 @@ enum PageType {
|
|||
BOOK
|
||||
FILE
|
||||
HIGHLIGHTS
|
||||
IMAGE
|
||||
PROFILE
|
||||
TWEET
|
||||
UNKNOWN
|
||||
VIDEO
|
||||
WEBSITE
|
||||
}
|
||||
|
||||
input ParseResult {
|
||||
byline: String
|
||||
content: String!
|
||||
dir: String
|
||||
excerpt: String!
|
||||
language: String
|
||||
length: Int!
|
||||
previewImage: String
|
||||
publishedDate: Date
|
||||
siteIcon: String
|
||||
siteName: String
|
||||
textContent: String!
|
||||
title: String!
|
||||
}
|
||||
|
||||
input PreparedDocumentInput {
|
||||
document: String!
|
||||
pageInfo: PageInfoInput!
|
||||
|
|
@ -971,25 +1279,31 @@ type Profile {
|
|||
|
||||
type Query {
|
||||
apiKeys: ApiKeysResult!
|
||||
article(slug: String!, username: String!): ArticleResult!
|
||||
articleSavingRequest(id: ID!): ArticleSavingRequestResult!
|
||||
article(format: String, slug: String!, username: String!): ArticleResult!
|
||||
articleSavingRequest(id: ID, url: String): ArticleSavingRequestResult!
|
||||
articles(after: String, first: Int, includePending: Boolean, query: String, sharedOnly: Boolean, sort: SortParams): ArticlesResult!
|
||||
deviceTokens: DeviceTokensResult!
|
||||
feedArticles(after: String, first: Int, sharedByUser: ID, sort: SortParams): FeedArticlesResult!
|
||||
filters: FiltersResult!
|
||||
getFollowers(userId: ID): GetFollowersResult!
|
||||
getFollowing(userId: ID): GetFollowingResult!
|
||||
getUserPersonalization: GetUserPersonalizationResult!
|
||||
groups: GroupsResult!
|
||||
hello: String
|
||||
integrations: IntegrationsResult!
|
||||
labels: LabelsResult!
|
||||
me: User
|
||||
newsletterEmails: NewsletterEmailsResult!
|
||||
recentEmails: RecentEmailsResult!
|
||||
recentSearches: RecentSearchesResult!
|
||||
reminder(linkId: ID!): ReminderResult!
|
||||
search(after: String, first: Int, query: String): SearchResult!
|
||||
rules(enabled: Boolean): RulesResult!
|
||||
search(after: String, first: Int, format: String, includeContent: Boolean, query: String): SearchResult!
|
||||
sendInstallInstructions: SendInstallInstructionsResult!
|
||||
sharedArticle(selectedHighlightId: String, slug: String!, username: String!): SharedArticleResult!
|
||||
subscriptions(sort: SortParams): SubscriptionsResult!
|
||||
typeaheadSearch(first: Int, query: String!): TypeaheadSearchResult!
|
||||
updatesSince(after: String, first: Int, since: Date!): UpdatesSinceResult!
|
||||
updatesSince(after: String, first: Int, since: Date!, sort: SortParams): UpdatesSinceResult!
|
||||
user(userId: ID, username: String): UserResult!
|
||||
users: UsersResult!
|
||||
validateUsername(username: String!): Boolean!
|
||||
|
|
@ -1021,6 +1335,128 @@ type ReadState {
|
|||
readingTime: Int
|
||||
}
|
||||
|
||||
type RecentEmail {
|
||||
createdAt: Date!
|
||||
from: String!
|
||||
html: String
|
||||
id: ID!
|
||||
subject: String!
|
||||
text: String!
|
||||
to: String!
|
||||
type: String!
|
||||
}
|
||||
|
||||
type RecentEmailsError {
|
||||
errorCodes: [RecentEmailsErrorCode!]!
|
||||
}
|
||||
|
||||
enum RecentEmailsErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union RecentEmailsResult = RecentEmailsError | RecentEmailsSuccess
|
||||
|
||||
type RecentEmailsSuccess {
|
||||
recentEmails: [RecentEmail!]!
|
||||
}
|
||||
|
||||
type RecentSearch {
|
||||
createdAt: Date!
|
||||
id: ID!
|
||||
term: String!
|
||||
}
|
||||
|
||||
type RecentSearchesError {
|
||||
errorCodes: [RecentSearchesErrorCode!]!
|
||||
}
|
||||
|
||||
enum RecentSearchesErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union RecentSearchesResult = RecentSearchesError | RecentSearchesSuccess
|
||||
|
||||
type RecentSearchesSuccess {
|
||||
searches: [RecentSearch!]!
|
||||
}
|
||||
|
||||
type RecommendError {
|
||||
errorCodes: [RecommendErrorCode!]!
|
||||
}
|
||||
|
||||
enum RecommendErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
type RecommendHighlightsError {
|
||||
errorCodes: [RecommendHighlightsErrorCode!]!
|
||||
}
|
||||
|
||||
enum RecommendHighlightsErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input RecommendHighlightsInput {
|
||||
groupIds: [ID!]!
|
||||
highlightIds: [ID!]!
|
||||
note: String
|
||||
pageId: ID!
|
||||
}
|
||||
|
||||
union RecommendHighlightsResult = RecommendHighlightsError | RecommendHighlightsSuccess
|
||||
|
||||
type RecommendHighlightsSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
input RecommendInput {
|
||||
groupIds: [ID!]!
|
||||
note: String
|
||||
pageId: ID!
|
||||
recommendedWithHighlights: Boolean
|
||||
}
|
||||
|
||||
union RecommendResult = RecommendError | RecommendSuccess
|
||||
|
||||
type RecommendSuccess {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Recommendation {
|
||||
id: ID!
|
||||
name: String!
|
||||
note: String
|
||||
recommendedAt: Date!
|
||||
user: RecommendingUser
|
||||
}
|
||||
|
||||
type RecommendationGroup {
|
||||
admins: [User!]!
|
||||
canPost: Boolean!
|
||||
canSeeMembers: Boolean!
|
||||
createdAt: Date!
|
||||
description: String
|
||||
id: ID!
|
||||
inviteUrl: String!
|
||||
members: [User!]!
|
||||
name: String!
|
||||
topics: [String!]
|
||||
updatedAt: Date!
|
||||
}
|
||||
|
||||
type RecommendingUser {
|
||||
name: String!
|
||||
profileImageURL: String
|
||||
userId: String!
|
||||
username: String!
|
||||
}
|
||||
|
||||
type Reminder {
|
||||
archiveUntil: Boolean!
|
||||
id: ID!
|
||||
|
|
@ -1079,6 +1515,48 @@ type RevokeApiKeySuccess {
|
|||
apiKey: ApiKey!
|
||||
}
|
||||
|
||||
type Rule {
|
||||
actions: [RuleAction!]!
|
||||
createdAt: Date!
|
||||
enabled: Boolean!
|
||||
filter: String!
|
||||
id: ID!
|
||||
name: String!
|
||||
updatedAt: Date!
|
||||
}
|
||||
|
||||
type RuleAction {
|
||||
params: [String!]!
|
||||
type: RuleActionType!
|
||||
}
|
||||
|
||||
input RuleActionInput {
|
||||
params: [String!]!
|
||||
type: RuleActionType!
|
||||
}
|
||||
|
||||
enum RuleActionType {
|
||||
ADD_LABEL
|
||||
ARCHIVE
|
||||
MARK_AS_READ
|
||||
SEND_NOTIFICATION
|
||||
}
|
||||
|
||||
type RulesError {
|
||||
errorCodes: [RulesErrorCode!]!
|
||||
}
|
||||
|
||||
enum RulesErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
union RulesResult = RulesError | RulesSuccess
|
||||
|
||||
type RulesSuccess {
|
||||
rules: [Rule!]!
|
||||
}
|
||||
|
||||
type SaveArticleReadingProgressError {
|
||||
errorCodes: [SaveArticleReadingProgressErrorCode!]!
|
||||
}
|
||||
|
|
@ -1093,6 +1571,7 @@ input SaveArticleReadingProgressInput {
|
|||
id: ID!
|
||||
readingProgressAnchorIndex: Int!
|
||||
readingProgressPercent: Float!
|
||||
readingProgressTopPercent: Float
|
||||
}
|
||||
|
||||
union SaveArticleReadingProgressResult = SaveArticleReadingProgressError | SaveArticleReadingProgressSuccess
|
||||
|
|
@ -1107,21 +1586,50 @@ type SaveError {
|
|||
}
|
||||
|
||||
enum SaveErrorCode {
|
||||
EMBEDDED_HIGHLIGHT_FAILED
|
||||
UNAUTHORIZED
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
input SaveFileInput {
|
||||
clientRequestId: ID!
|
||||
labels: [CreateLabelInput!]
|
||||
source: String!
|
||||
state: ArticleSavingRequestStatus
|
||||
uploadFileId: ID!
|
||||
url: String!
|
||||
}
|
||||
|
||||
type SaveFilterError {
|
||||
errorCodes: [SaveFilterErrorCode!]!
|
||||
}
|
||||
|
||||
enum SaveFilterErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input SaveFilterInput {
|
||||
description: String
|
||||
filter: String!
|
||||
id: ID
|
||||
name: String!
|
||||
}
|
||||
|
||||
union SaveFilterResult = SaveFilterError | SaveFilterSuccess
|
||||
|
||||
type SaveFilterSuccess {
|
||||
filter: Filter!
|
||||
}
|
||||
|
||||
input SavePageInput {
|
||||
clientRequestId: ID!
|
||||
labels: [CreateLabelInput!]
|
||||
originalContent: String!
|
||||
parseResult: ParseResult
|
||||
source: String!
|
||||
state: ArticleSavingRequestStatus
|
||||
title: String
|
||||
url: String!
|
||||
}
|
||||
|
|
@ -1135,7 +1643,9 @@ type SaveSuccess {
|
|||
|
||||
input SaveUrlInput {
|
||||
clientRequestId: ID!
|
||||
labels: [CreateLabelInput!]
|
||||
source: String!
|
||||
state: ArticleSavingRequestStatus
|
||||
url: String!
|
||||
}
|
||||
|
||||
|
|
@ -1144,12 +1654,14 @@ type SearchError {
|
|||
}
|
||||
|
||||
enum SearchErrorCode {
|
||||
QUERY_TOO_LONG
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
type SearchItem {
|
||||
annotation: String
|
||||
author: String
|
||||
content: String
|
||||
contentReader: ContentReader!
|
||||
createdAt: Date!
|
||||
description: String
|
||||
|
|
@ -1168,8 +1680,11 @@ type SearchItem {
|
|||
readAt: Date
|
||||
readingProgressAnchorIndex: Int!
|
||||
readingProgressPercent: Float!
|
||||
readingProgressTopPercent: Float
|
||||
recommendations: [Recommendation!]
|
||||
savedAt: Date!
|
||||
shortId: String
|
||||
siteIcon: String
|
||||
siteName: String
|
||||
slug: String!
|
||||
state: ArticleSavingRequestStatus
|
||||
|
|
@ -1180,6 +1695,7 @@ type SearchItem {
|
|||
updatedAt: Date
|
||||
uploadFileId: ID
|
||||
url: String!
|
||||
wordsCount: Int
|
||||
}
|
||||
|
||||
type SearchItemEdge {
|
||||
|
|
@ -1287,8 +1803,9 @@ enum SetIntegrationErrorCode {
|
|||
input SetIntegrationInput {
|
||||
enabled: Boolean!
|
||||
id: ID
|
||||
name: String!
|
||||
token: String!
|
||||
type: IntegrationType!
|
||||
type: IntegrationType
|
||||
}
|
||||
|
||||
union SetIntegrationResult = SetIntegrationError | SetIntegrationSuccess
|
||||
|
|
@ -1323,6 +1840,31 @@ type SetLabelsSuccess {
|
|||
labels: [Label!]!
|
||||
}
|
||||
|
||||
type SetRuleError {
|
||||
errorCodes: [SetRuleErrorCode!]!
|
||||
}
|
||||
|
||||
enum SetRuleErrorCode {
|
||||
BAD_REQUEST
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input SetRuleInput {
|
||||
actions: [RuleActionInput!]!
|
||||
description: String
|
||||
enabled: Boolean!
|
||||
filter: String!
|
||||
id: ID
|
||||
name: String!
|
||||
}
|
||||
|
||||
union SetRuleResult = SetRuleError | SetRuleSuccess
|
||||
|
||||
type SetRuleSuccess {
|
||||
rule: Rule!
|
||||
}
|
||||
|
||||
type SetShareArticleError {
|
||||
errorCodes: [SetShareArticleErrorCode!]!
|
||||
}
|
||||
|
|
@ -1373,6 +1915,7 @@ type SetUserPersonalizationError {
|
|||
}
|
||||
|
||||
enum SetUserPersonalizationErrorCode {
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
|
|
@ -1382,6 +1925,10 @@ input SetUserPersonalizationInput {
|
|||
libraryLayoutType: String
|
||||
librarySortOrder: SortOrder
|
||||
margin: Int
|
||||
speechRate: String
|
||||
speechSecondaryVoice: String
|
||||
speechVoice: String
|
||||
speechVolume: String
|
||||
theme: String
|
||||
}
|
||||
|
||||
|
|
@ -1485,6 +2032,7 @@ type SubscribeSuccess {
|
|||
type Subscription {
|
||||
createdAt: Date!
|
||||
description: String
|
||||
icon: String
|
||||
id: ID!
|
||||
name: String!
|
||||
newsletterEmail: String!
|
||||
|
|
@ -1576,6 +2124,8 @@ enum UpdateHighlightErrorCode {
|
|||
input UpdateHighlightInput {
|
||||
annotation: String
|
||||
highlightId: ID!
|
||||
html: String
|
||||
quote: String
|
||||
sharedAt: Date
|
||||
}
|
||||
|
||||
|
|
@ -1664,8 +2214,11 @@ enum UpdatePageErrorCode {
|
|||
}
|
||||
|
||||
input UpdatePageInput {
|
||||
byline: String
|
||||
description: String
|
||||
pageId: ID!
|
||||
publishedAt: Date
|
||||
savedAt: Date
|
||||
title: String
|
||||
}
|
||||
|
||||
|
|
@ -1818,6 +2371,28 @@ enum UploadFileStatus {
|
|||
INITIALIZED
|
||||
}
|
||||
|
||||
type UploadImportFileError {
|
||||
errorCodes: [UploadImportFileErrorCode!]!
|
||||
}
|
||||
|
||||
enum UploadImportFileErrorCode {
|
||||
BAD_REQUEST
|
||||
UNAUTHORIZED
|
||||
UPLOAD_DAILY_LIMIT_EXCEEDED
|
||||
}
|
||||
|
||||
union UploadImportFileResult = UploadImportFileError | UploadImportFileSuccess
|
||||
|
||||
type UploadImportFileSuccess {
|
||||
uploadSignedUrl: String
|
||||
}
|
||||
|
||||
enum UploadImportFileType {
|
||||
MATTER
|
||||
POCKET
|
||||
URL_LIST
|
||||
}
|
||||
|
||||
type User {
|
||||
followersCount: Int
|
||||
friendsCount: Int
|
||||
|
|
@ -1851,6 +2426,10 @@ type UserPersonalization {
|
|||
libraryLayoutType: String
|
||||
librarySortOrder: SortOrder
|
||||
margin: Int
|
||||
speechRate: String
|
||||
speechSecondaryVoice: String
|
||||
speechVoice: String
|
||||
speechVolume: String
|
||||
theme: String
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ suspend fun DataService.createWebHighlight(jsonString: String) {
|
|||
val highlight = Highlight(
|
||||
highlightId = createHighlightInput.id,
|
||||
shortId = createHighlightInput.shortId,
|
||||
quote = createHighlightInput.quote,
|
||||
quote = createHighlightInput.quote.getOrNull(),
|
||||
prefix = null,
|
||||
suffix = null,
|
||||
patch = createHighlightInput.patch,
|
||||
patch = createHighlightInput.patch.getOrNull(),
|
||||
annotation = createHighlightInput.annotation.getOrNull(),
|
||||
createdAt = null,
|
||||
updatedAt = null,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): S
|
|||
slug = it.slug,
|
||||
isArchived = it.isArchived,
|
||||
contentReader = it.contentReader.rawValue,
|
||||
content = null
|
||||
content = null,
|
||||
wordsCount = it.wordsCount
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ import app.omnivore.omnivore.networking.*
|
|||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.apollographql.apollo3.api.Optional.Companion.absent
|
||||
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
||||
suspend fun DataService.startSyncChannels() {
|
||||
for (savedItem in savedItemSyncChannel) {
|
||||
|
|
@ -130,8 +133,8 @@ private suspend fun DataService.syncHighlight(highlight: Highlight) {
|
|||
annotation = Optional.presentIfNotNull(highlight.annotation),
|
||||
articleId = savedItemID ?: "",
|
||||
id = highlight.highlightId,
|
||||
patch = highlight.patch ?: "",
|
||||
quote = highlight.quote ?: "",
|
||||
patch = Optional.presentIfNotNull(highlight.patch),
|
||||
quote = Optional.presentIfNotNull(highlight.quote),
|
||||
shortId = highlight.shortId ?: ""
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ data class CreateHighlightParams(
|
|||
annotation = Optional.presentIfNotNull(`annotation`),
|
||||
articleId = articleId ?: "",
|
||||
id = id ?: "",
|
||||
patch = patch ?: "",
|
||||
quote = quote ?: "",
|
||||
patch = Optional.presentIfNotNull(patch),
|
||||
quote = Optional.presentIfNotNull(quote),
|
||||
shortId = shortId ?: ""
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
|
|||
slug = article.articleFields.slug,
|
||||
isArchived = article.articleFields.isArchived,
|
||||
contentReader = article.articleFields.contentReader.rawValue,
|
||||
content = article.articleFields.content
|
||||
content = article.articleFields.content,
|
||||
wordsCount = article.articleFields.wordsCount
|
||||
)
|
||||
|
||||
return SavedItemQueryResponse(item = savedItem, highlights, labels = savedItemLabels, state = article.articleFields.state?.rawValue ?: "")
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ suspend fun Networker.search(
|
|||
slug = it.node.slug,
|
||||
isArchived = it.node.isArchived,
|
||||
contentReader = it.node.contentReader.rawValue,
|
||||
content = null
|
||||
content = null,
|
||||
wordsCount = it.node.wordsCount,
|
||||
),
|
||||
labels = (it.node.labels ?: listOf()).map { label ->
|
||||
SavedItemLabel(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import app.omnivore.omnivore.persistence.entities.*
|
|||
SavedItemAndSavedItemLabelCrossRef::class,
|
||||
SavedItemAndHighlightCrossRef::class
|
||||
],
|
||||
version = 3
|
||||
version = 5
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun viewerDao(): ViewerDao
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ data class Highlight(
|
|||
val createdAt: String?,
|
||||
val createdByMe: Boolean,
|
||||
val markedForDeletion: Boolean = false,
|
||||
var patch: String,
|
||||
var patch: String?,
|
||||
var prefix: String?,
|
||||
var quote: String,
|
||||
var quote: String?,
|
||||
var serverSyncStatus: Int = ServerSyncStatus.IS_SYNCED.rawValue,
|
||||
var shortId: String,
|
||||
val suffix: String?,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ data class SavedItem(
|
|||
val originalHtml: String? = null,
|
||||
@ColumnInfo(typeAffinity = ColumnInfo.BLOB) val pdfData: ByteArray? = null,
|
||||
var serverSyncStatus: Int = 0,
|
||||
val tempPDFURL: String? = null
|
||||
val tempPDFURL: String? = null,
|
||||
val wordsCount: Int? = null
|
||||
|
||||
// hasMany highlights
|
||||
// hasMany labels
|
||||
|
|
@ -78,6 +79,7 @@ data class SavedItemCardData(
|
|||
val contentReader: String?,
|
||||
val savedAt: String,
|
||||
val readingProgress: Double,
|
||||
val wordsCount: Int?
|
||||
) {
|
||||
fun publisherDisplayName(): String? {
|
||||
return publisherURLString?.toUri()?.host
|
||||
|
|
@ -161,5 +163,5 @@ interface SavedItemDao {
|
|||
|
||||
|
||||
object SavedItemQueryConstants {
|
||||
const val columns = "savedItemId, slug, publisherURLString, title, author, imageURLString, isArchived, pageURLString, contentReader, savedAt, readingProgress"
|
||||
const val columns = "savedItemId, slug, publisherURLString, title, author, imageURLString, isArchived, pageURLString, contentReader, savedAt, readingProgress, wordsCount"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
|
|||
import app.omnivore.omnivore.graphql.generated.type.SetLabelsInput
|
||||
import app.omnivore.omnivore.networking.*
|
||||
import app.omnivore.omnivore.persistence.entities.*
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
|
@ -141,7 +142,8 @@ class LibraryViewModel @Inject constructor(
|
|||
imageURLString = it.imageURLString,
|
||||
isArchived = it.isArchived,
|
||||
pageURLString = it.pageURLString,
|
||||
contentReader = it.contentReader
|
||||
contentReader = it.contentReader,
|
||||
wordsCount = it.wordsCount
|
||||
),
|
||||
labels = listOf()
|
||||
)
|
||||
|
|
@ -222,7 +224,8 @@ class LibraryViewModel @Inject constructor(
|
|||
pageURLString = it.pageURLString,
|
||||
contentReader = it.contentReader,
|
||||
savedAt = it.savedAt,
|
||||
readingProgress = it.readingProgress
|
||||
readingProgress = it.readingProgress,
|
||||
wordsCount = it.wordsCount
|
||||
),
|
||||
labels = listOf()
|
||||
)
|
||||
|
|
@ -388,7 +391,7 @@ class LibraryViewModel @Inject constructor(
|
|||
fun createNewSavedItemLabel(labelName: String, hexColorValue: String) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val newLabel = networker.createNewLabel(CreateLabelInput(color = hexColorValue, name = labelName))
|
||||
val newLabel = networker.createNewLabel(CreateLabelInput(color = Optional.presentIfNotNull(hexColorValue), name = labelName))
|
||||
|
||||
newLabel?.let {
|
||||
val savedItemLabel = SavedItemLabel(
|
||||
|
|
|
|||
|
|
@ -134,13 +134,16 @@ class PDFReaderActivity: AppCompatActivity(), DocumentListener, TextSelectionMan
|
|||
|
||||
private fun loadHighlights(highlights: List<Highlight>) {
|
||||
for (highlight in highlights) {
|
||||
val highlightAnnotation = fragment
|
||||
.document
|
||||
?.annotationProvider
|
||||
?.createAnnotationFromInstantJson(highlight.patch)
|
||||
val patch = highlight.patch
|
||||
if (patch != null) {
|
||||
val highlightAnnotation = fragment
|
||||
.document
|
||||
?.annotationProvider
|
||||
?.createAnnotationFromInstantJson(patch)
|
||||
|
||||
highlightAnnotation?.let {
|
||||
fragment.addAnnotationToPage(highlightAnnotation, true)
|
||||
highlightAnnotation?.let {
|
||||
fragment.addAnnotationToPage(highlightAnnotation, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ class PDFReaderViewModel @Inject constructor(
|
|||
annotation = Optional.presentIfNotNull(note),
|
||||
articleId = itemID,
|
||||
id = highlightID,
|
||||
patch = newAnnotation.toInstantJson(),
|
||||
quote = quote,
|
||||
patch = Optional.presentIfNotNull(newAnnotation.toInstantJson()),
|
||||
quote = Optional.presentIfNotNull(quote),
|
||||
shortId = shortID,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import app.omnivore.omnivore.networking.*
|
|||
import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.ui.library.SavedItemAction
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
|
|
@ -394,7 +396,8 @@ class WebReaderViewModel @Inject constructor(
|
|||
fun createNewSavedItemLabel(labelName: String, hexColorValue: String) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val newLabel = networker.createNewLabel(CreateLabelInput(color = hexColorValue, name = labelName))
|
||||
|
||||
val newLabel = networker.createNewLabel(CreateLabelInput(color = Optional.presentIfNotNull(hexColorValue), name = labelName))
|
||||
|
||||
newLabel?.let {
|
||||
val savedItemLabel = SavedItemLabel(
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ fun SavedItemCard(cardData: SavedItemCardData, labels: List<SavedItemLabel>, onC
|
|||
.padding(end = 20.dp)
|
||||
.defaultMinSize(minHeight = 55.dp)
|
||||
) {
|
||||
readInfo(item = cardData)
|
||||
|
||||
Text(
|
||||
text = cardData.title,
|
||||
style = TextStyle(
|
||||
|
|
@ -66,7 +68,11 @@ fun SavedItemCard(cardData: SavedItemCardData, labels: List<SavedItemLabel>, onC
|
|||
if (cardData.author != null && cardData.author != "") {
|
||||
Text(
|
||||
text = byline(cardData),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
style = TextStyle(
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = Color(red = 137, green = 137, blue = 137)
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
|
|
@ -88,7 +94,7 @@ fun SavedItemCard(cardData: SavedItemCardData, labels: List<SavedItemLabel>, onC
|
|||
contentDescription = "Image associated with saved item",
|
||||
modifier = Modifier
|
||||
.size(55.dp, 73.dp)
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -141,3 +147,96 @@ fun byline(item: SavedItemCardData): String {
|
|||
|
||||
return ""
|
||||
}
|
||||
|
||||
//
|
||||
//var readingSpeed: Int64 {
|
||||
// var result = UserDefaults.standard.integer(forKey: UserDefaultKey.userWordsPerMinute.rawValue)
|
||||
// if result <= 0 {
|
||||
// result = 235
|
||||
// }
|
||||
// return Int64(result)
|
||||
//}
|
||||
|
||||
fun estimatedReadingTime(item: SavedItemCardData): String {
|
||||
item.wordsCount?.let {
|
||||
if (it > 0) {
|
||||
val readLen = Math.max(1, it / 235)
|
||||
return "$readLen MIN READ • "
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fun readingProgress(item: SavedItemCardData): String {
|
||||
// If there is no wordsCount don't show progress because it will make no sense
|
||||
item.wordsCount?.let {
|
||||
if (it > 0) {
|
||||
val intVal = item.readingProgress.toInt()
|
||||
return "$intVal%"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
//
|
||||
//var highlightsText: String {
|
||||
// if let highlights = item.highlights, highlights.count > 0 {
|
||||
// let fmted = LocalText.pluralizedText(key: "number_of_highlights", count: highlights.count)
|
||||
// if item.wordsCount > 0 {
|
||||
// return " • \(fmted)"
|
||||
// }
|
||||
// return fmted
|
||||
// }
|
||||
// return ""
|
||||
//}
|
||||
//
|
||||
//var notesText: String {
|
||||
// let notes = item.highlights?.filter { item in
|
||||
// if let highlight = item as? Highlight {
|
||||
// return !(highlight.annotation ?? "").isEmpty
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// if let notes = notes, notes.count > 0 {
|
||||
// let fmted = LocalText.pluralizedText(key: "number_of_notes", count: notes.count)
|
||||
// if item.wordsCount > 0 {
|
||||
// return " • \(fmted)"
|
||||
// }
|
||||
// return fmted
|
||||
// }
|
||||
// return ""
|
||||
//}
|
||||
|
||||
@Composable
|
||||
fun readInfo(item: SavedItemCardData) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().defaultMinSize(minHeight = 15.dp)
|
||||
) {
|
||||
Text(
|
||||
text = estimatedReadingTime(item),
|
||||
style = TextStyle(
|
||||
fontSize = 11.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = Color(red = 137, green = 137, blue = 137)
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
|
||||
Text(
|
||||
text = readingProgress(item),
|
||||
style = TextStyle(
|
||||
fontSize = 11.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = if (item.readingProgress > 1) Color(red = 85, green = 185, blue = 56) else Color(red = 137, green = 137, blue = 137)
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
|
||||
// Text("\(highlightsText)")
|
||||
//
|
||||
// Text("\(notesText)")
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue