Merge pull request #2687 from omnivore-app/feat/mobile-highlight-colors

Add support for viewing coloured highlights in iOS and Android
This commit is contained in:
Jackson Harper 2023-08-28 09:25:12 +08:00 committed by GitHub
commit 27a5ab5042
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 812 additions and 182 deletions

View file

@ -7,6 +7,9 @@ apple_graphql_gen:
apple_extension_gen:
$(MAKE) -C apple extension_gen
android_graphql_gen:
cp packages/api/src/generated/schema.graphql android/Omnivore/app/src/main/graphql/schema.graphqls
droid:
@if ! [ -e android/Omnivore/app/src/main/res/values/secrets.xml ]; then \
cp android/Omnivore/secrets.xml android/Omnivore/app/src/main/res/values/secrets.xml; \

View file

@ -17,8 +17,8 @@ android {
applicationId "app.omnivore.omnivore"
minSdk 26
targetSdk 33
versionCode 93
versionName "0.0.93"
versionCode 97
versionName "0.0.97"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

File diff suppressed because one or more lines are too long

View file

@ -56,6 +56,7 @@ fragment HighlightFields on Highlight {
createdAt
updatedAt
sharedAt
color
}
fragment LabelFields on Label {

View file

@ -1,9 +1,4 @@
directive @sanitize(
allowedTags: [String]
maxLength: Int
minLength: 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!]!
@ -155,9 +150,7 @@ enum ArticleSavingRequestErrorCode {
UNAUTHORIZED
}
union ArticleSavingRequestResult =
ArticleSavingRequestError
| ArticleSavingRequestSuccess
union ArticleSavingRequestResult = ArticleSavingRequestError | ArticleSavingRequestSuccess
enum ArticleSavingRequestStatus {
ARCHIVED
@ -195,6 +188,7 @@ type BulkActionError {
}
enum BulkActionErrorCode {
BAD_REQUEST
UNAUTHORIZED
}
@ -205,8 +199,10 @@ type BulkActionSuccess {
}
enum BulkActionType {
ADD_LABELS
ARCHIVE
DELETE
MARK_AS_READ
}
enum ContentReader {
@ -255,9 +251,7 @@ input CreateArticleSavingRequestInput {
url: String!
}
union CreateArticleSavingRequestResult =
CreateArticleSavingRequestError
| CreateArticleSavingRequestSuccess
union CreateArticleSavingRequestResult = CreateArticleSavingRequestError | CreateArticleSavingRequestSuccess
type CreateArticleSavingRequestSuccess {
articleSavingRequest: ArticleSavingRequest!
@ -309,6 +303,7 @@ enum CreateHighlightErrorCode {
input CreateHighlightInput {
annotation: String
articleId: ID!
color: String
highlightPositionAnchorIndex: Int
highlightPositionPercent: Float
html: String
@ -338,9 +333,7 @@ input CreateHighlightReplyInput {
text: String!
}
union CreateHighlightReplyResult =
CreateHighlightReplyError
| CreateHighlightReplySuccess
union CreateHighlightReplyResult = CreateHighlightReplyError | CreateHighlightReplySuccess
type CreateHighlightReplySuccess {
highlightReply: HighlightReply!
@ -384,9 +377,7 @@ enum CreateNewsletterEmailErrorCode {
UNAUTHORIZED
}
union CreateNewsletterEmailResult =
CreateNewsletterEmailError
| CreateNewsletterEmailSuccess
union CreateNewsletterEmailResult = CreateNewsletterEmailError | CreateNewsletterEmailSuccess
type CreateNewsletterEmailSuccess {
newsletterEmail: NewsletterEmail!
@ -494,9 +485,7 @@ enum DeleteHighlightReplyErrorCode {
UNAUTHORIZED
}
union DeleteHighlightReplyResult =
DeleteHighlightReplyError
| DeleteHighlightReplySuccess
union DeleteHighlightReplyResult = DeleteHighlightReplyError | DeleteHighlightReplySuccess
type DeleteHighlightReplySuccess {
highlightReply: HighlightReply!
@ -518,9 +507,7 @@ enum DeleteIntegrationErrorCode {
UNAUTHORIZED
}
union DeleteIntegrationResult =
DeleteIntegrationError
| DeleteIntegrationSuccess
union DeleteIntegrationResult = DeleteIntegrationError | DeleteIntegrationSuccess
type DeleteIntegrationSuccess {
integration: Integration!
@ -532,6 +519,7 @@ type DeleteLabelError {
enum DeleteLabelErrorCode {
BAD_REQUEST
FORBIDDEN
NOT_FOUND
UNAUTHORIZED
}
@ -552,9 +540,7 @@ enum DeleteNewsletterEmailErrorCode {
UNAUTHORIZED
}
union DeleteNewsletterEmailResult =
DeleteNewsletterEmailError
| DeleteNewsletterEmailSuccess
union DeleteNewsletterEmailResult = DeleteNewsletterEmailError | DeleteNewsletterEmailSuccess
type DeleteNewsletterEmailSuccess {
newsletterEmail: NewsletterEmail!
@ -689,6 +675,7 @@ type FeedArticlesSuccess {
}
type Filter {
category: String!
createdAt: Date!
description: String
filter: String!
@ -771,9 +758,7 @@ enum GetUserPersonalizationErrorCode {
UNAUTHORIZED
}
union GetUserPersonalizationResult =
GetUserPersonalizationError
| GetUserPersonalizationSuccess
union GetUserPersonalizationResult = GetUserPersonalizationError | GetUserPersonalizationSuccess
type GetUserPersonalizationSuccess {
userPersonalization: UserPersonalization
@ -821,6 +806,7 @@ type GroupsSuccess {
type Highlight {
annotation: String
color: String
createdAt: Date!
createdByMe: Boolean!
highlightPositionAnchorIndex: Int
@ -869,9 +855,7 @@ enum ImportFromIntegrationErrorCode {
UNAUTHORIZED
}
union ImportFromIntegrationResult =
ImportFromIntegrationError
| ImportFromIntegrationSuccess
union ImportFromIntegrationResult = ImportFromIntegrationError | ImportFromIntegrationSuccess
type ImportFromIntegrationSuccess {
success: Boolean!
@ -882,6 +866,7 @@ type Integration {
enabled: Boolean!
id: ID!
name: String!
taskName: String
token: String!
type: IntegrationType!
updatedAt: Date!
@ -928,6 +913,7 @@ type Label {
createdAt: Date
description: String
id: ID!
internal: Boolean
name: String!
position: Int
}
@ -1050,6 +1036,7 @@ enum MergeHighlightErrorCode {
input MergeHighlightInput {
annotation: String
articleId: ID!
color: String
highlightPositionAnchorIndex: Int
highlightPositionPercent: Float
html: String
@ -1113,16 +1100,12 @@ type MoveLabelSuccess {
type Mutation {
addPopularRead(name: String!): AddPopularReadResult!
bulkAction(action: BulkActionType!, query: String): BulkActionResult!
bulkAction(action: BulkActionType!, async: Boolean, expectedCount: Int, labelIds: [ID!], query: String!): BulkActionResult!
createArticle(input: CreateArticleInput!): CreateArticleResult!
createArticleSavingRequest(
input: CreateArticleSavingRequestInput!
): CreateArticleSavingRequestResult!
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
createGroup(input: CreateGroupInput!): CreateGroupResult!
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
createHighlightReply(
input: CreateHighlightReplyInput!
): CreateHighlightReplyResult!
createHighlightReply(input: CreateHighlightReplyInput!): CreateHighlightReplyResult!
createLabel(input: CreateLabelInput!): CreateLabelResult!
createNewsletterEmail: CreateNewsletterEmailResult!
createReaction(input: CreateReactionInput!): CreateReactionResult!
@ -1151,20 +1134,17 @@ type Mutation {
moveLabel(input: MoveLabelInput!): MoveLabelResult!
optInFeature(input: OptInFeatureInput!): OptInFeatureResult!
recommend(input: RecommendInput!): RecommendResult!
recommendHighlights(
input: RecommendHighlightsInput!
): RecommendHighlightsResult!
recommendHighlights(input: RecommendHighlightsInput!): RecommendHighlightsResult!
reportItem(input: ReportItemInput!): ReportItemResult!
revokeApiKey(id: ID!): RevokeApiKeyResult!
saveArticleReadingProgress(
input: SaveArticleReadingProgressInput!
): SaveArticleReadingProgressResult!
saveArticleReadingProgress(input: SaveArticleReadingProgressInput!): SaveArticleReadingProgressResult!
saveFile(input: SaveFileInput!): SaveResult!
saveFilter(input: SaveFilterInput!): SaveFilterResult!
savePage(input: SavePageInput!): SaveResult!
saveUrl(input: SaveUrlInput!): SaveResult!
setBookmarkArticle(input: SetBookmarkArticleInput!): SetBookmarkArticleResult!
setDeviceToken(input: SetDeviceTokenInput!): SetDeviceTokenResult!
setFavoriteArticle(id: ID!): SetFavoriteArticleResult!
setFollow(input: SetFollowInput!): SetFollowResult!
setIntegration(input: SetIntegrationInput!): SetIntegrationResult!
setLabels(input: SetLabelsInput!): SetLabelsResult!
@ -1173,32 +1153,22 @@ type Mutation {
setRule(input: SetRuleInput!): SetRuleResult!
setShareArticle(input: SetShareArticleInput!): SetShareArticleResult!
setShareHighlight(input: SetShareHighlightInput!): SetShareHighlightResult!
setUserPersonalization(
input: SetUserPersonalizationInput!
): SetUserPersonalizationResult!
setUserPersonalization(input: SetUserPersonalizationInput!): SetUserPersonalizationResult!
setWebhook(input: SetWebhookInput!): SetWebhookResult!
subscribe(name: String!): SubscribeResult!
unsubscribe(name: String!): UnsubscribeResult!
subscribe(input: SubscribeInput!): SubscribeResult!
unsubscribe(name: String!, subscriptionId: ID): UnsubscribeResult!
updateHighlight(input: UpdateHighlightInput!): UpdateHighlightResult!
updateHighlightReply(
input: UpdateHighlightReplyInput!
): UpdateHighlightReplyResult!
updateHighlightReply(input: UpdateHighlightReplyInput!): UpdateHighlightReplyResult!
updateLabel(input: UpdateLabelInput!): UpdateLabelResult!
updateLinkShareInfo(
input: UpdateLinkShareInfoInput!
): UpdateLinkShareInfoResult!
updateLinkShareInfo(input: UpdateLinkShareInfoInput!): UpdateLinkShareInfoResult!
updatePage(input: UpdatePageInput!): UpdatePageResult!
updateReminder(input: UpdateReminderInput!): UpdateReminderResult!
updateSharedComment(
input: UpdateSharedCommentInput!
): UpdateSharedCommentResult!
updateSharedComment(input: UpdateSharedCommentInput!): UpdateSharedCommentResult!
updateSubscription(input: UpdateSubscriptionInput!): UpdateSubscriptionResult!
updateUser(input: UpdateUserInput!): UpdateUserResult!
updateUserProfile(input: UpdateUserProfileInput!): UpdateUserProfileResult!
uploadFileRequest(input: UploadFileRequestInput!): UploadFileRequestResult!
uploadImportFile(
contentType: String!
type: UploadImportFileType!
): UploadImportFileResult!
uploadImportFile(contentType: String!, type: UploadImportFileType!): UploadImportFileResult!
}
type NewsletterEmail {
@ -1323,21 +1293,9 @@ type Query {
apiKeys: ApiKeysResult!
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!
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!
feedArticles(after: String, first: Int, sharedByUser: ID, sort: SortParams): FeedArticlesResult!
filters: FiltersResult!
getFollowers(userId: ID): GetFollowersResult!
getFollowing(userId: ID): GetFollowingResult!
@ -1352,27 +1310,12 @@ type Query {
recentSearches: RecentSearchesResult!
reminder(linkId: ID!): ReminderResult!
rules(enabled: Boolean): RulesResult!
search(
after: String
first: Int
format: String
includeContent: Boolean
query: String
): SearchResult!
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!
sharedArticle(selectedHighlightId: String, slug: String!, username: String!): SharedArticleResult!
subscriptions(sort: SortParams, type: SubscriptionType): SubscriptionsResult!
typeaheadSearch(first: Int, query: String!): TypeaheadSearchResult!
updatesSince(
after: String
first: Int
since: Date!
sort: SortParams
): UpdatesSinceResult!
updatesSince(after: String, first: Int, since: Date!, sort: SortParams): UpdatesSinceResult!
user(userId: ID, username: String): UserResult!
users: UsersResult!
validateUsername(username: String!): Boolean!
@ -1478,9 +1421,7 @@ input RecommendHighlightsInput {
pageId: ID!
}
union RecommendHighlightsResult =
RecommendHighlightsError
| RecommendHighlightsSuccess
union RecommendHighlightsResult = RecommendHighlightsError | RecommendHighlightsSuccess
type RecommendHighlightsSuccess {
success: Boolean!
@ -1590,6 +1531,7 @@ type Rule {
actions: [RuleAction!]!
createdAt: Date!
enabled: Boolean!
eventTypes: [RuleEventType!]!
filter: String!
id: ID!
name: String!
@ -1613,6 +1555,11 @@ enum RuleActionType {
SEND_NOTIFICATION
}
enum RuleEventType {
PAGE_CREATED
PAGE_UPDATED
}
type RulesError {
errorCodes: [RulesErrorCode!]!
}
@ -1645,9 +1592,7 @@ input SaveArticleReadingProgressInput {
readingProgressTopPercent: Float
}
union SaveArticleReadingProgressResult =
SaveArticleReadingProgressError
| SaveArticleReadingProgressSuccess
union SaveArticleReadingProgressResult = SaveArticleReadingProgressError | SaveArticleReadingProgressSuccess
type SaveArticleReadingProgressSuccess {
updatedArticle: Article!
@ -1684,6 +1629,7 @@ enum SaveFilterErrorCode {
}
input SaveFilterInput {
category: String!
description: String
filter: String!
id: ID
@ -1701,6 +1647,9 @@ input SavePageInput {
labels: [CreateLabelInput!]
originalContent: String!
parseResult: ParseResult
publishedAt: Date
rssFeedUrl: String
savedAt: Date
source: String!
state: ArticleSavingRequestStatus
title: String
@ -1717,11 +1666,13 @@ type SaveSuccess {
input SaveUrlInput {
clientRequestId: ID!
labels: [CreateLabelInput!]
locale: String
publishedAt: Date
savedAt: Date
source: String!
state: ArticleSavingRequestStatus
url: String!
timezone: String
locale: String
url: String!
}
type SearchError {
@ -1735,7 +1686,9 @@ enum SearchErrorCode {
type SearchItem {
annotation: String
archivedAt: Date
author: String
color: String
content: String
contentReader: ContentReader!
createdAt: Date!
@ -1796,9 +1749,7 @@ enum SendInstallInstructionsErrorCode {
UNAUTHORIZED
}
union SendInstallInstructionsResult =
SendInstallInstructionsError
| SendInstallInstructionsSuccess
union SendInstallInstructionsResult = SendInstallInstructionsError | SendInstallInstructionsSuccess
type SendInstallInstructionsSuccess {
sent: Boolean!
@ -1818,9 +1769,7 @@ input SetBookmarkArticleInput {
bookmark: Boolean!
}
union SetBookmarkArticleResult =
SetBookmarkArticleError
| SetBookmarkArticleSuccess
union SetBookmarkArticleResult = SetBookmarkArticleError | SetBookmarkArticleSuccess
type SetBookmarkArticleSuccess {
bookmarkedArticle: Article!
@ -1847,6 +1796,23 @@ type SetDeviceTokenSuccess {
deviceToken: DeviceToken!
}
type SetFavoriteArticleError {
errorCodes: [SetFavoriteArticleErrorCode!]!
}
enum SetFavoriteArticleErrorCode {
ALREADY_EXISTS
BAD_REQUEST
NOT_FOUND
UNAUTHORIZED
}
union SetFavoriteArticleResult = SetFavoriteArticleError | SetFavoriteArticleSuccess
type SetFavoriteArticleSuccess {
favoriteArticle: Article!
}
type SetFollowError {
errorCodes: [SetFollowErrorCode!]!
}
@ -1905,11 +1871,13 @@ enum SetLabelsErrorCode {
input SetLabelsForHighlightInput {
highlightId: ID!
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
}
input SetLabelsInput {
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
pageId: ID!
}
@ -1933,6 +1901,7 @@ input SetRuleInput {
actions: [RuleActionInput!]!
description: String
enabled: Boolean!
eventTypes: [RuleEventType!]!
filter: String!
id: ID
name: String!
@ -1983,9 +1952,7 @@ input SetShareHighlightInput {
share: Boolean!
}
union SetShareHighlightResult =
SetShareHighlightError
| SetShareHighlightSuccess
union SetShareHighlightResult = SetShareHighlightError | SetShareHighlightSuccess
type SetShareHighlightSuccess {
highlight: Highlight!
@ -2013,9 +1980,7 @@ input SetUserPersonalizationInput {
theme: String
}
union SetUserPersonalizationResult =
SetUserPersonalizationError
| SetUserPersonalizationSuccess
union SetUserPersonalizationResult = SetUserPersonalizationError | SetUserPersonalizationSuccess
type SetUserPersonalizationSuccess {
updatedUserPersonalization: UserPersonalization!
@ -2102,10 +2067,17 @@ type SubscribeError {
enum SubscribeErrorCode {
ALREADY_SUBSCRIBED
BAD_REQUEST
EXCEEDED_MAX_SUBSCRIPTIONS
NOT_FOUND
UNAUTHORIZED
}
input SubscribeInput {
name: String
subscriptionType: SubscriptionType
url: String
}
union SubscribeResult = SubscribeError | SubscribeSuccess
type SubscribeSuccess {
@ -2113,13 +2085,16 @@ type SubscribeSuccess {
}
type Subscription {
count: Int!
createdAt: Date!
description: String
icon: String
id: ID!
lastFetchedAt: Date
name: String!
newsletterEmail: String!
newsletterEmail: String
status: SubscriptionStatus!
type: SubscriptionType!
unsubscribeHttpUrl: String
unsubscribeMailTo: String
updatedAt: Date!
@ -2132,6 +2107,11 @@ enum SubscriptionStatus {
UNSUBSCRIBED
}
enum SubscriptionType {
NEWSLETTER
RSS
}
type SubscriptionsError {
errorCodes: [SubscriptionsErrorCode!]!
}
@ -2163,6 +2143,7 @@ enum TypeaheadSearchErrorCode {
}
type TypeaheadSearchItem {
contentReader: ContentReader!
id: ID!
siteName: String
slug: String!
@ -2206,6 +2187,7 @@ enum UpdateHighlightErrorCode {
input UpdateHighlightInput {
annotation: String
color: String
highlightId: ID!
html: String
quote: String
@ -2227,9 +2209,7 @@ input UpdateHighlightReplyInput {
text: String!
}
union UpdateHighlightReplyResult =
UpdateHighlightReplyError
| UpdateHighlightReplySuccess
union UpdateHighlightReplyResult = UpdateHighlightReplyError | UpdateHighlightReplySuccess
type UpdateHighlightReplySuccess {
highlightReply: HighlightReply!
@ -2280,9 +2260,7 @@ input UpdateLinkShareInfoInput {
title: String!
}
union UpdateLinkShareInfoResult =
UpdateLinkShareInfoError
| UpdateLinkShareInfoSuccess
union UpdateLinkShareInfoResult = UpdateLinkShareInfoError | UpdateLinkShareInfoSuccess
type UpdateLinkShareInfoSuccess {
message: String!
@ -2304,8 +2282,10 @@ input UpdatePageInput {
byline: String
description: String
pageId: ID!
previewImage: String
publishedAt: Date
savedAt: Date
state: ArticleSavingRequestStatus
title: String
}
@ -2358,15 +2338,37 @@ input UpdateSharedCommentInput {
sharedComment: String!
}
union UpdateSharedCommentResult =
UpdateSharedCommentError
| UpdateSharedCommentSuccess
union UpdateSharedCommentResult = UpdateSharedCommentError | UpdateSharedCommentSuccess
type UpdateSharedCommentSuccess {
articleID: ID!
sharedComment: String!
}
type UpdateSubscriptionError {
errorCodes: [UpdateSubscriptionErrorCode!]!
}
enum UpdateSubscriptionErrorCode {
BAD_REQUEST
NOT_FOUND
UNAUTHORIZED
}
input UpdateSubscriptionInput {
description: String
id: ID!
lastFetchedAt: Date
name: String
status: SubscriptionStatus
}
union UpdateSubscriptionResult = UpdateSubscriptionError | UpdateSubscriptionSuccess
type UpdateSubscriptionSuccess {
subscription: Subscription!
}
type UpdateUserError {
errorCodes: [UpdateUserErrorCode!]!
}
@ -2402,9 +2404,7 @@ input UpdateUserProfileInput {
username: String
}
union UpdateUserProfileResult =
UpdateUserProfileError
| UpdateUserProfileSuccess
union UpdateUserProfileResult = UpdateUserProfileError | UpdateUserProfileSuccess
type UpdateUserProfileSuccess {
user: User!
@ -2448,9 +2448,7 @@ input UploadFileRequestInput {
url: String!
}
union UploadFileRequestResult =
UploadFileRequestError
| UploadFileRequestSuccess
union UploadFileRequestResult = UploadFileRequestError | UploadFileRequestSuccess
type UploadFileRequestSuccess {
createdPageId: String
@ -2490,8 +2488,7 @@ type User {
followersCount: Int
friendsCount: Int
id: ID!
isFriend: Boolean
@deprecated(reason: "isFriend has been replaced with viewerIsFollowing")
isFriend: Boolean @deprecated(reason: "isFriend has been replaced with viewerIsFollowing")
isFullUser: Boolean
name: String!
picture: String

View file

@ -27,7 +27,8 @@ suspend fun DataService.createWebHighlight(jsonString: String) {
annotation = createHighlightInput.annotation.getOrNull(),
createdAt = null,
updatedAt = null,
createdByMe = false
createdByMe = false,
color = null,
)
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_CREATION.rawValue
@ -64,7 +65,8 @@ suspend fun DataService.createNoteHighlight(savedItemId: String, note: String):
annotation = note,
createdAt = null,
updatedAt = null,
createdByMe = true
createdByMe = true,
color = null
)
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_CREATION.rawValue

View file

@ -85,6 +85,7 @@ suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): S
suffix = highlight.highlightFields.suffix,
createdAt = null,
updatedAt = highlight.highlightFields.updatedAt as String?,
color = highlight.highlightFields.color
)
} ?: listOf()
SavedItemWithLabelsAndHighlights(

View file

@ -150,7 +150,8 @@ suspend fun Networker.createHighlight(input: CreateHighlightInput): Highlight? {
annotation = createdHighlight.highlightFields.annotation,
createdAt = createdHighlight.highlightFields.createdAt.toString(),
updatedAt = createdHighlight.highlightFields.updatedAt.toString(),
createdByMe = createdHighlight.highlightFields.createdByMe
createdByMe = createdHighlight.highlightFields.createdByMe,
color = createdHighlight.highlightFields.color
)
} else {
return null

View file

@ -53,7 +53,8 @@ suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
annotation = it.highlightFields.annotation,
createdAt = it.highlightFields.createdAt as String?,
updatedAt = it.highlightFields.updatedAt as String?,
createdByMe = it.highlightFields.createdByMe
createdByMe = it.highlightFields.createdByMe,
color = it.highlightFields.color
)
}

View file

@ -82,6 +82,7 @@ suspend fun Networker.search(
suffix = highlight.highlightFields.suffix,
updatedAt = highlight.highlightFields.updatedAt as String?,
createdAt = highlight.highlightFields.createdAt as String?,
color = highlight.highlightFields.color
)
}
)

View file

@ -13,7 +13,7 @@ import app.omnivore.omnivore.persistence.entities.*
SavedItemAndSavedItemLabelCrossRef::class,
SavedItemAndHighlightCrossRef::class
],
version = 8
version = 9
)
abstract class AppDatabase : RoomDatabase() {
abstract fun viewerDao(): ViewerDao

View file

@ -21,7 +21,8 @@ data class Highlight(
var serverSyncStatus: Int = ServerSyncStatus.IS_SYNCED.rawValue,
var shortId: String,
val suffix: String?,
val updatedAt: String?
val updatedAt: String?,
val color: String?
)
@Entity(

View file

@ -331,7 +331,7 @@ class LibraryViewModel @Inject constructor(
val allLabels = syncedLabels + createdLabels
val input = SetLabelsInput(labelIds = allLabels.map { it.savedItemLabelId }, pageId = savedItemID)
val input = SetLabelsInput(labelIds = Optional.presentIfNotNull(allLabels.map { it.savedItemLabelId }), pageId = savedItemID)
val networkResult = networker.updateLabelsForSavedItem(input)
val crossRefs = allLabels.map {

View file

@ -115,7 +115,7 @@ fun ReaderPreferencesView(webReaderViewModel: WebReaderViewModel) {
webReaderViewModel.setFontSize(it.toInt())
},
steps = 10,
valueRange = 8f..28f,
valueRange = 10f..48f,
)
Text("Margin", style = TextStyle(

View file

@ -22,6 +22,7 @@ import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCros
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
import app.omnivore.omnivore.ui.components.LabelSwatchHelper
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
@ -467,7 +468,7 @@ class WebReaderViewModel @Inject constructor(
}
}
val input = SetLabelsInput(labelIds = namedLabels.map { it.savedItemLabelId }, pageId = savedItemID)
val input = SetLabelsInput(labelIds = Optional.presentIfNotNull(namedLabels.map { it.savedItemLabelId }), pageId = savedItemID)
val networkResult = networker.updateLabelsForSavedItem(input)
// TODO: assign a server sync status to these

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="21G419" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="21G531" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Highlight" representedClassName="Highlight" syncable="YES" codeGenerationType="class">
<attribute name="annotation" optional="YES" attributeType="String"/>
<attribute name="color" optional="YES" attributeType="String"/>
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="createdByMe" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>

View file

@ -5,7 +5,7 @@ public struct Subscription {
public let description: String?
public let subscriptionID: String
public let name: String
public let newsletterEmailAddress: String
public let newsletterEmailAddress: String?
public let status: SubscriptionStatus
public let unsubscribeHttpUrl: String?
public let unsubscribeMailTo: String?
@ -18,7 +18,7 @@ public struct Subscription {
description: String?,
subscriptionID: String,
name: String,
newsletterEmailAddress: String,
newsletterEmailAddress: String?,
status: SubscriptionStatus,
unsubscribeHttpUrl: String?,
unsubscribeMailTo: String?,

View file

@ -7282,6 +7282,7 @@ extension Objects {
struct Highlight {
let __typename: TypeName = .highlight
let annotation: [String: String]
let color: [String: String]
let createdAt: [String: DateTime]
let createdByMe: [String: Bool]
let highlightPositionAnchorIndex: [String: Int]
@ -7323,6 +7324,10 @@ extension Objects.Highlight: Decodable {
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "color":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "createdAt":
if let value = try container.decode(DateTime?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -7406,6 +7411,7 @@ extension Objects.Highlight: Decodable {
}
annotation = map["annotation"]
color = map["color"]
createdAt = map["createdAt"]
createdByMe = map["createdByMe"]
highlightPositionAnchorIndex = map["highlightPositionAnchorIndex"]
@ -7443,6 +7449,21 @@ extension Fields where TypeLock == Objects.Highlight {
}
}
func color() throws -> String? {
let field = GraphQLField.leaf(
name: "color",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
return data.color[field.alias!]
case .mocking:
return nil
}
}
func createdAt() throws -> DateTime {
let field = GraphQLField.leaf(
name: "createdAt",
@ -8138,6 +8159,7 @@ extension Objects {
let enabled: [String: Bool]
let id: [String: String]
let name: [String: String]
let taskName: [String: String]
let token: [String: String]
let type: [String: Enums.IntegrationType]
let updatedAt: [String: DateTime]
@ -8176,6 +8198,10 @@ extension Objects.Integration: Decodable {
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "taskName":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "token":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -8202,6 +8228,7 @@ extension Objects.Integration: Decodable {
enabled = map["enabled"]
id = map["id"]
name = map["name"]
taskName = map["taskName"]
token = map["token"]
type = map["type"]
updatedAt = map["updatedAt"]
@ -8281,6 +8308,21 @@ extension Fields where TypeLock == Objects.Integration {
}
}
func taskName() throws -> String? {
let field = GraphQLField.leaf(
name: "taskName",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
return data.taskName[field.alias!]
case .mocking:
return nil
}
}
func token() throws -> String {
let field = GraphQLField.leaf(
name: "token",
@ -10405,6 +10447,7 @@ extension Objects {
let updatePage: [String: Unions.UpdatePageResult]
let updateReminder: [String: Unions.UpdateReminderResult]
let updateSharedComment: [String: Unions.UpdateSharedCommentResult]
let updateSubscription: [String: Unions.UpdateSubscriptionResult]
let updateUser: [String: Unions.UpdateUserResult]
let updateUserProfile: [String: Unions.UpdateUserProfileResult]
let uploadFileRequest: [String: Unions.UploadFileRequestResult]
@ -10688,6 +10731,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.UpdateSharedCommentResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "updateSubscription":
if let value = try container.decode(Unions.UpdateSubscriptionResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "updateUser":
if let value = try container.decode(Unions.UpdateUserResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -10779,6 +10826,7 @@ extension Objects.Mutation: Decodable {
updatePage = map["updatePage"]
updateReminder = map["updateReminder"]
updateSharedComment = map["updateSharedComment"]
updateSubscription = map["updateSubscription"]
updateUser = map["updateUser"]
updateUserProfile = map["updateUserProfile"]
uploadFileRequest = map["uploadFileRequest"]
@ -11851,10 +11899,10 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
func subscribe<Type>(name: String, selection: Selection<Type, Unions.SubscribeResult>) throws -> Type {
func subscribe<Type>(input: InputObjects.SubscribeInput, selection: Selection<Type, Unions.SubscribeResult>) throws -> Type {
let field = GraphQLField.composite(
name: "subscribe",
arguments: [Argument(name: "name", type: "String!", value: name)],
arguments: [Argument(name: "input", type: "SubscribeInput!", value: input)],
selection: selection.selection
)
select(field)
@ -11870,10 +11918,10 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
func unsubscribe<Type>(name: String, selection: Selection<Type, Unions.UnsubscribeResult>) throws -> Type {
func unsubscribe<Type>(name: String, subscriptionId: OptionalArgument<String> = .absent(), selection: Selection<Type, Unions.UnsubscribeResult>) throws -> Type {
let field = GraphQLField.composite(
name: "unsubscribe",
arguments: [Argument(name: "name", type: "String!", value: name)],
arguments: [Argument(name: "name", type: "String!", value: name), Argument(name: "subscriptionId", type: "ID", value: subscriptionId)],
selection: selection.selection
)
select(field)
@ -12022,6 +12070,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
func updateSubscription<Type>(input: InputObjects.UpdateSubscriptionInput, selection: Selection<Type, Unions.UpdateSubscriptionResult>) throws -> Type {
let field = GraphQLField.composite(
name: "updateSubscription",
arguments: [Argument(name: "input", type: "UpdateSubscriptionInput!", value: input)],
selection: selection.selection
)
select(field)
switch response {
case let .decoding(data):
if let data = data.updateSubscription[field.alias!] {
return try selection.decode(data: data)
}
throw HttpError.badpayload
case .mocking:
return selection.mock()
}
}
func updateUser<Type>(input: InputObjects.UpdateUserInput, selection: Selection<Type, Unions.UpdateUserResult>) throws -> Type {
let field = GraphQLField.composite(
name: "updateUser",
@ -13850,10 +13917,10 @@ extension Fields where TypeLock == Objects.Query {
}
}
func subscriptions<Type>(sort: OptionalArgument<InputObjects.SortParams> = .absent(), selection: Selection<Type, Unions.SubscriptionsResult>) throws -> Type {
func subscriptions<Type>(sort: OptionalArgument<InputObjects.SortParams> = .absent(), type: OptionalArgument<Enums.SubscriptionType> = .absent(), selection: Selection<Type, Unions.SubscriptionsResult>) throws -> Type {
let field = GraphQLField.composite(
name: "subscriptions",
arguments: [Argument(name: "sort", type: "SortParams", value: sort)],
arguments: [Argument(name: "sort", type: "SortParams", value: sort), Argument(name: "type", type: "SubscriptionType", value: type)],
selection: selection.selection
)
select(field)
@ -16222,6 +16289,7 @@ extension Objects {
let actions: [String: [Objects.RuleAction]]
let createdAt: [String: DateTime]
let enabled: [String: Bool]
let eventTypes: [String: [Enums.RuleEventType]]
let filter: [String: String]
let id: [String: String]
let name: [String: String]
@ -16257,6 +16325,10 @@ extension Objects.Rule: Decodable {
if let value = try container.decode(Bool?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "eventTypes":
if let value = try container.decode([Enums.RuleEventType]?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "filter":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -16286,6 +16358,7 @@ extension Objects.Rule: Decodable {
actions = map["actions"]
createdAt = map["createdAt"]
enabled = map["enabled"]
eventTypes = map["eventTypes"]
filter = map["filter"]
id = map["id"]
name = map["name"]
@ -16349,6 +16422,24 @@ extension Fields where TypeLock == Objects.Rule {
}
}
func eventTypes() throws -> [Enums.RuleEventType] {
let field = GraphQLField.leaf(
name: "eventTypes",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.eventTypes[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return []
}
}
func filter() throws -> String {
let field = GraphQLField.leaf(
name: "filter",
@ -17154,6 +17245,7 @@ extension Objects {
let annotation: [String: String]
let archivedAt: [String: DateTime]
let author: [String: String]
let color: [String: String]
let content: [String: String]
let contentReader: [String: Enums.ContentReader]
let createdAt: [String: DateTime]
@ -17220,6 +17312,10 @@ extension Objects.SearchItem: Decodable {
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "color":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "content":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -17373,6 +17469,7 @@ extension Objects.SearchItem: Decodable {
annotation = map["annotation"]
archivedAt = map["archivedAt"]
author = map["author"]
color = map["color"]
content = map["content"]
contentReader = map["contentReader"]
createdAt = map["createdAt"]
@ -17457,6 +17554,21 @@ extension Fields where TypeLock == Objects.SearchItem {
}
}
func color() throws -> String? {
let field = GraphQLField.leaf(
name: "color",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
return data.color[field.alias!]
case .mocking:
return nil
}
}
func content() throws -> String? {
let field = GraphQLField.leaf(
name: "content",
@ -20196,13 +20308,16 @@ extension Selection where TypeLock == Never, Type == Never {
extension Objects {
struct Subscription {
let __typename: TypeName = .subscription
let count: [String: Int]
let createdAt: [String: DateTime]
let description: [String: String]
let icon: [String: String]
let id: [String: String]
let lastFetchedAt: [String: DateTime]
let name: [String: String]
let newsletterEmail: [String: String]
let status: [String: Enums.SubscriptionStatus]
let type: [String: Enums.SubscriptionType]
let unsubscribeHttpUrl: [String: String]
let unsubscribeMailTo: [String: String]
let updatedAt: [String: DateTime]
@ -20226,6 +20341,10 @@ extension Objects.Subscription: Decodable {
let field = GraphQLField.getFieldNameFromAlias(alias)
switch field {
case "count":
if let value = try container.decode(Int?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "createdAt":
if let value = try container.decode(DateTime?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -20242,6 +20361,10 @@ extension Objects.Subscription: Decodable {
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "lastFetchedAt":
if let value = try container.decode(DateTime?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "name":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -20254,6 +20377,10 @@ extension Objects.Subscription: Decodable {
if let value = try container.decode(Enums.SubscriptionStatus?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "type":
if let value = try container.decode(Enums.SubscriptionType?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "unsubscribeHttpUrl":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -20280,13 +20407,16 @@ extension Objects.Subscription: Decodable {
}
}
count = map["count"]
createdAt = map["createdAt"]
description = map["description"]
icon = map["icon"]
id = map["id"]
lastFetchedAt = map["lastFetchedAt"]
name = map["name"]
newsletterEmail = map["newsletterEmail"]
status = map["status"]
type = map["type"]
unsubscribeHttpUrl = map["unsubscribeHttpUrl"]
unsubscribeMailTo = map["unsubscribeMailTo"]
updatedAt = map["updatedAt"]
@ -20295,6 +20425,24 @@ extension Objects.Subscription: Decodable {
}
extension Fields where TypeLock == Objects.Subscription {
func count() throws -> Int {
let field = GraphQLField.leaf(
name: "count",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.count[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return Int.mockValue
}
}
func createdAt() throws -> DateTime {
let field = GraphQLField.leaf(
name: "createdAt",
@ -20361,6 +20509,21 @@ extension Fields where TypeLock == Objects.Subscription {
}
}
func lastFetchedAt() throws -> DateTime? {
let field = GraphQLField.leaf(
name: "lastFetchedAt",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
return data.lastFetchedAt[field.alias!]
case .mocking:
return nil
}
}
func name() throws -> String {
let field = GraphQLField.leaf(
name: "name",
@ -20379,7 +20542,7 @@ extension Fields where TypeLock == Objects.Subscription {
}
}
func newsletterEmail() throws -> String {
func newsletterEmail() throws -> String? {
let field = GraphQLField.leaf(
name: "newsletterEmail",
arguments: []
@ -20388,12 +20551,9 @@ extension Fields where TypeLock == Objects.Subscription {
switch response {
case let .decoding(data):
if let data = data.newsletterEmail[field.alias!] {
return data
}
throw HttpError.badpayload
return data.newsletterEmail[field.alias!]
case .mocking:
return String.mockValue
return nil
}
}
@ -20415,6 +20575,24 @@ extension Fields where TypeLock == Objects.Subscription {
}
}
func type() throws -> Enums.SubscriptionType {
let field = GraphQLField.leaf(
name: "type",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.type[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return Enums.SubscriptionType.allCases.first!
}
}
func unsubscribeHttpUrl() throws -> String? {
let field = GraphQLField.leaf(
name: "unsubscribeHttpUrl",
@ -22108,6 +22286,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias UpdateSharedCommentSuccess<T> = Selection<T, Objects.UpdateSharedCommentSuccess>
}
extension Objects {
struct UpdateSubscriptionError {
let __typename: TypeName = .updateSubscriptionError
let errorCodes: [String: [Enums.UpdateSubscriptionErrorCode]]
enum TypeName: String, Codable {
case updateSubscriptionError = "UpdateSubscriptionError"
}
}
}
extension Objects.UpdateSubscriptionError: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
var map = HashMap()
for codingKey in container.allKeys {
if codingKey.isTypenameKey { continue }
let alias = codingKey.stringValue
let field = GraphQLField.getFieldNameFromAlias(alias)
switch field {
case "errorCodes":
if let value = try container.decode([Enums.UpdateSubscriptionErrorCode]?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
default:
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Unknown key \(field)."
)
)
}
}
errorCodes = map["errorCodes"]
}
}
extension Fields where TypeLock == Objects.UpdateSubscriptionError {
func errorCodes() throws -> [Enums.UpdateSubscriptionErrorCode] {
let field = GraphQLField.leaf(
name: "errorCodes",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.errorCodes[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return []
}
}
}
extension Selection where TypeLock == Never, Type == Never {
typealias UpdateSubscriptionError<T> = Selection<T, Objects.UpdateSubscriptionError>
}
extension Objects {
struct UpdateSubscriptionSuccess {
let __typename: TypeName = .updateSubscriptionSuccess
let subscription: [String: Objects.Subscription]
enum TypeName: String, Codable {
case updateSubscriptionSuccess = "UpdateSubscriptionSuccess"
}
}
}
extension Objects.UpdateSubscriptionSuccess: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
var map = HashMap()
for codingKey in container.allKeys {
if codingKey.isTypenameKey { continue }
let alias = codingKey.stringValue
let field = GraphQLField.getFieldNameFromAlias(alias)
switch field {
case "subscription":
if let value = try container.decode(Objects.Subscription?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
default:
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Unknown key \(field)."
)
)
}
}
subscription = map["subscription"]
}
}
extension Fields where TypeLock == Objects.UpdateSubscriptionSuccess {
func subscription<Type>(selection: Selection<Type, Objects.Subscription>) throws -> Type {
let field = GraphQLField.composite(
name: "subscription",
arguments: [],
selection: selection.selection
)
select(field)
switch response {
case let .decoding(data):
if let data = data.subscription[field.alias!] {
return try selection.decode(data: data)
}
throw HttpError.badpayload
case .mocking:
return selection.mock()
}
}
}
extension Selection where TypeLock == Never, Type == Never {
typealias UpdateSubscriptionSuccess<T> = Selection<T, Objects.UpdateSubscriptionSuccess>
}
extension Objects {
struct UpdateUserError {
let __typename: TypeName = .updateUserError
@ -30499,6 +30808,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias UpdateSharedCommentResult<T> = Selection<T, Unions.UpdateSharedCommentResult>
}
extension Unions {
struct UpdateSubscriptionResult {
let __typename: TypeName
let errorCodes: [String: [Enums.UpdateSubscriptionErrorCode]]
let subscription: [String: Objects.Subscription]
enum TypeName: String, Codable {
case updateSubscriptionError = "UpdateSubscriptionError"
case updateSubscriptionSuccess = "UpdateSubscriptionSuccess"
}
}
}
extension Unions.UpdateSubscriptionResult: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
var map = HashMap()
for codingKey in container.allKeys {
if codingKey.isTypenameKey { continue }
let alias = codingKey.stringValue
let field = GraphQLField.getFieldNameFromAlias(alias)
switch field {
case "errorCodes":
if let value = try container.decode([Enums.UpdateSubscriptionErrorCode]?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "subscription":
if let value = try container.decode(Objects.Subscription?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
default:
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Unknown key \(field)."
)
)
}
}
__typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
errorCodes = map["errorCodes"]
subscription = map["subscription"]
}
}
extension Fields where TypeLock == Unions.UpdateSubscriptionResult {
func on<Type>(updateSubscriptionError: Selection<Type, Objects.UpdateSubscriptionError>, updateSubscriptionSuccess: Selection<Type, Objects.UpdateSubscriptionSuccess>) throws -> Type {
select([GraphQLField.fragment(type: "UpdateSubscriptionError", selection: updateSubscriptionError.selection), GraphQLField.fragment(type: "UpdateSubscriptionSuccess", selection: updateSubscriptionSuccess.selection)])
switch response {
case let .decoding(data):
switch data.__typename {
case .updateSubscriptionError:
let data = Objects.UpdateSubscriptionError(errorCodes: data.errorCodes)
return try updateSubscriptionError.decode(data: data)
case .updateSubscriptionSuccess:
let data = Objects.UpdateSubscriptionSuccess(subscription: data.subscription)
return try updateSubscriptionSuccess.decode(data: data)
}
case .mocking:
return updateSubscriptionError.mock()
}
}
}
extension Selection where TypeLock == Never, Type == Never {
typealias UpdateSubscriptionResult<T> = Selection<T, Unions.UpdateSubscriptionResult>
}
extension Unions {
struct UpdateUserProfileResult {
let __typename: TypeName
@ -31891,6 +32274,15 @@ extension Enums {
}
}
extension Enums {
/// RuleEventType
enum RuleEventType: String, CaseIterable, Codable {
case pageCreated = "PAGE_CREATED"
case pageUpdated = "PAGE_UPDATED"
}
}
extension Enums {
/// RulesErrorCode
enum RulesErrorCode: String, CaseIterable, Codable {
@ -32133,6 +32525,8 @@ extension Enums {
case badRequest = "BAD_REQUEST"
case exceededMaxSubscriptions = "EXCEEDED_MAX_SUBSCRIPTIONS"
case notFound = "NOT_FOUND"
case unauthorized = "UNAUTHORIZED"
@ -32150,6 +32544,15 @@ extension Enums {
}
}
extension Enums {
/// SubscriptionType
enum SubscriptionType: String, CaseIterable, Codable {
case newsletter = "NEWSLETTER"
case rss = "RSS"
}
}
extension Enums {
/// SubscriptionsErrorCode
enum SubscriptionsErrorCode: String, CaseIterable, Codable {
@ -32273,6 +32676,17 @@ extension Enums {
}
}
extension Enums {
/// UpdateSubscriptionErrorCode
enum UpdateSubscriptionErrorCode: String, CaseIterable, Codable {
case badRequest = "BAD_REQUEST"
case notFound = "NOT_FOUND"
case unauthorized = "UNAUTHORIZED"
}
}
extension Enums {
/// UpdateUserErrorCode
enum UpdateUserErrorCode: String, CaseIterable, Codable {
@ -32551,6 +32965,8 @@ extension InputObjects {
var articleId: String
var color: OptionalArgument<String> = .absent()
var highlightPositionAnchorIndex: OptionalArgument<Int> = .absent()
var highlightPositionPercent: OptionalArgument<Double> = .absent()
@ -32577,6 +32993,7 @@ extension InputObjects {
var container = encoder.container(keyedBy: CodingKeys.self)
if annotation.hasValue { try container.encode(annotation, forKey: .annotation) }
try container.encode(articleId, forKey: .articleId)
if color.hasValue { try container.encode(color, forKey: .color) }
if highlightPositionAnchorIndex.hasValue { try container.encode(highlightPositionAnchorIndex, forKey: .highlightPositionAnchorIndex) }
if highlightPositionPercent.hasValue { try container.encode(highlightPositionPercent, forKey: .highlightPositionPercent) }
if html.hasValue { try container.encode(html, forKey: .html) }
@ -32593,6 +33010,7 @@ extension InputObjects {
enum CodingKeys: String, CodingKey {
case annotation
case articleId
case color
case highlightPositionAnchorIndex
case highlightPositionPercent
case html
@ -32791,6 +33209,8 @@ extension InputObjects {
var articleId: String
var color: OptionalArgument<String> = .absent()
var highlightPositionAnchorIndex: OptionalArgument<Int> = .absent()
var highlightPositionPercent: OptionalArgument<Double> = .absent()
@ -32815,6 +33235,7 @@ extension InputObjects {
var container = encoder.container(keyedBy: CodingKeys.self)
if annotation.hasValue { try container.encode(annotation, forKey: .annotation) }
try container.encode(articleId, forKey: .articleId)
if color.hasValue { try container.encode(color, forKey: .color) }
if highlightPositionAnchorIndex.hasValue { try container.encode(highlightPositionAnchorIndex, forKey: .highlightPositionAnchorIndex) }
if highlightPositionPercent.hasValue { try container.encode(highlightPositionPercent, forKey: .highlightPositionPercent) }
if html.hasValue { try container.encode(html, forKey: .html) }
@ -32830,6 +33251,7 @@ extension InputObjects {
enum CodingKeys: String, CodingKey {
case annotation
case articleId
case color
case highlightPositionAnchorIndex
case highlightPositionPercent
case html
@ -33221,6 +33643,12 @@ extension InputObjects {
var parseResult: OptionalArgument<InputObjects.ParseResult> = .absent()
var publishedAt: OptionalArgument<DateTime> = .absent()
var rssFeedUrl: OptionalArgument<String> = .absent()
var savedAt: OptionalArgument<DateTime> = .absent()
var source: String
var state: OptionalArgument<Enums.ArticleSavingRequestStatus> = .absent()
@ -33235,6 +33663,9 @@ extension InputObjects {
if labels.hasValue { try container.encode(labels, forKey: .labels) }
try container.encode(originalContent, forKey: .originalContent)
if parseResult.hasValue { try container.encode(parseResult, forKey: .parseResult) }
if publishedAt.hasValue { try container.encode(publishedAt, forKey: .publishedAt) }
if rssFeedUrl.hasValue { try container.encode(rssFeedUrl, forKey: .rssFeedUrl) }
if savedAt.hasValue { try container.encode(savedAt, forKey: .savedAt) }
try container.encode(source, forKey: .source)
if state.hasValue { try container.encode(state, forKey: .state) }
if title.hasValue { try container.encode(title, forKey: .title) }
@ -33246,6 +33677,9 @@ extension InputObjects {
case labels
case originalContent
case parseResult
case publishedAt
case rssFeedUrl
case savedAt
case source
case state
case title
@ -33260,26 +33694,42 @@ extension InputObjects {
var labels: OptionalArgument<[InputObjects.CreateLabelInput]> = .absent()
var locale: OptionalArgument<String> = .absent()
var publishedAt: OptionalArgument<DateTime> = .absent()
var savedAt: OptionalArgument<DateTime> = .absent()
var source: String
var state: OptionalArgument<Enums.ArticleSavingRequestStatus> = .absent()
var timezone: OptionalArgument<String> = .absent()
var url: String
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(clientRequestId, forKey: .clientRequestId)
if labels.hasValue { try container.encode(labels, forKey: .labels) }
if locale.hasValue { try container.encode(locale, forKey: .locale) }
if publishedAt.hasValue { try container.encode(publishedAt, forKey: .publishedAt) }
if savedAt.hasValue { try container.encode(savedAt, forKey: .savedAt) }
try container.encode(source, forKey: .source)
if state.hasValue { try container.encode(state, forKey: .state) }
if timezone.hasValue { try container.encode(timezone, forKey: .timezone) }
try container.encode(url, forKey: .url)
}
enum CodingKeys: String, CodingKey {
case clientRequestId
case labels
case locale
case publishedAt
case savedAt
case source
case state
case timezone
case url
}
}
@ -33427,6 +33877,8 @@ extension InputObjects {
var enabled: Bool
var eventTypes: [Enums.RuleEventType]
var filter: String
var id: OptionalArgument<String> = .absent()
@ -33438,6 +33890,7 @@ extension InputObjects {
try container.encode(actions, forKey: .actions)
if description.hasValue { try container.encode(description, forKey: .description) }
try container.encode(enabled, forKey: .enabled)
try container.encode(eventTypes, forKey: .eventTypes)
try container.encode(filter, forKey: .filter)
if id.hasValue { try container.encode(id, forKey: .id) }
try container.encode(name, forKey: .name)
@ -33447,6 +33900,7 @@ extension InputObjects {
case actions
case description
case enabled
case eventTypes
case filter
case id
case name
@ -33605,10 +34059,35 @@ extension InputObjects {
}
}
extension InputObjects {
struct SubscribeInput: Encodable, Hashable {
var name: OptionalArgument<String> = .absent()
var subscriptionType: OptionalArgument<Enums.SubscriptionType> = .absent()
var url: OptionalArgument<String> = .absent()
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if name.hasValue { try container.encode(name, forKey: .name) }
if subscriptionType.hasValue { try container.encode(subscriptionType, forKey: .subscriptionType) }
if url.hasValue { try container.encode(url, forKey: .url) }
}
enum CodingKeys: String, CodingKey {
case name
case subscriptionType
case url
}
}
}
extension InputObjects {
struct UpdateHighlightInput: Encodable, Hashable {
var annotation: OptionalArgument<String> = .absent()
var color: OptionalArgument<String> = .absent()
var highlightId: String
var html: OptionalArgument<String> = .absent()
@ -33620,6 +34099,7 @@ extension InputObjects {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if annotation.hasValue { try container.encode(annotation, forKey: .annotation) }
if color.hasValue { try container.encode(color, forKey: .color) }
try container.encode(highlightId, forKey: .highlightId)
if html.hasValue { try container.encode(html, forKey: .html) }
if quote.hasValue { try container.encode(quote, forKey: .quote) }
@ -33628,6 +34108,7 @@ extension InputObjects {
enum CodingKeys: String, CodingKey {
case annotation
case color
case highlightId
case html
case quote
@ -33794,6 +34275,37 @@ extension InputObjects {
}
}
extension InputObjects {
struct UpdateSubscriptionInput: Encodable, Hashable {
var description: OptionalArgument<String> = .absent()
var id: String
var lastFetchedAt: OptionalArgument<DateTime> = .absent()
var name: OptionalArgument<String> = .absent()
var status: OptionalArgument<Enums.SubscriptionStatus> = .absent()
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if description.hasValue { try container.encode(description, forKey: .description) }
try container.encode(id, forKey: .id)
if lastFetchedAt.hasValue { try container.encode(lastFetchedAt, forKey: .lastFetchedAt) }
if name.hasValue { try container.encode(name, forKey: .name) }
if status.hasValue { try container.encode(status, forKey: .status) }
}
enum CodingKeys: String, CodingKey {
case description
case id
case lastFetchedAt
case name
case status
}
}
}
extension InputObjects {
struct UpdateUserInput: Encodable, Hashable {
var bio: OptionalArgument<String> = .absent()

View file

@ -13,7 +13,8 @@ public extension DataService {
articleId: String,
positionPercent: Double?,
positionAnchorIndex: Int?,
annotation: String? = nil
annotation: String? = nil,
color: String? = nil
) -> [String: Any]? {
let internalHighlight = InternalHighlight(
id: highlightID,
@ -29,6 +30,7 @@ public extension DataService {
createdBy: nil,
positionPercent: positionPercent,
positionAnchorIndex: positionAnchorIndex,
color: color,
labels: []
)
@ -60,6 +62,7 @@ public extension DataService {
createdBy: nil,
positionPercent: nil,
positionAnchorIndex: nil,
color: nil,
labels: []
)

View file

@ -30,6 +30,7 @@ extension DataService {
createdBy: nil,
positionPercent: positionPercent,
positionAnchorIndex: positionAnchorIndex,
color: nil,
labels: []
)

View file

@ -27,6 +27,7 @@ let highlightSelection = Selection.Highlight {
createdBy: try $0.user(selection: userProfileSelection),
positionPercent: try $0.highlightPositionPercent(),
positionAnchorIndex: try $0.highlightPositionAnchorIndex(),
color: try $0.color(),
labels: try $0.labels(selection: highlightLabelSelection.list.nullable) ?? []
)
}

View file

@ -17,6 +17,7 @@ struct InternalHighlight: Encodable {
let createdBy: InternalUserProfile?
let positionPercent: Double?
let positionAnchorIndex: Int?
let color: String?
var labels: [InternalLinkedItemLabel]
func asManagedObject(context: NSManagedObjectContext) -> Highlight {
@ -39,6 +40,7 @@ struct InternalHighlight: Encodable {
highlight.createdAt = createdAt
highlight.updatedAt = updatedAt
highlight.createdByMe = createdByMe
highlight.color = color
highlight.positionPercent = positionPercent ?? -1.0
if let positionAnchorIndex = positionAnchorIndex {
highlight.positionAnchorIndex = Int64(positionAnchorIndex)
@ -75,6 +77,7 @@ struct InternalHighlight: Encodable {
createdBy: InternalUserProfile.makeSingle(highlight.createdBy),
positionPercent: highlight.positionPercent,
positionAnchorIndex: Int(highlight.positionAnchorIndex),
color: highlight.color,
labels: InternalLinkedItemLabel.make(highlight.labels)
)
}

View file

@ -203,7 +203,7 @@ public enum WebFont: String, CaseIterable {
}, label: { Image(systemName: "textformat.size.smaller") })
.frame(width: 25, height: 25, alignment: .center)
CustomSlider(value: $storedFontSize, minValue: 10, maxValue: 42) { _ in
CustomSlider(value: $storedFontSize, minValue: 10, maxValue: 48) { _ in
if storedFontSize % 1 == 0 {
updateReaderPreferences()
}

File diff suppressed because one or more lines are too long

View file

@ -208,7 +208,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
const handleFontSizeChange = async (event: UpdateFontSizeEvent) => {
const newFontSize = event.fontSize ?? 18
if (newFontSize >= 10 && newFontSize <= 28) {
if (newFontSize >= 10 && newFontSize <= 48) {
updateFontSize(newFontSize)
}
}

View file

@ -355,7 +355,7 @@ function FontControls(props: FontControlsProps): JSX.Element {
</Button>
<TickedRangeSlider
min={10}
max={34}
max={48}
step={2}
value={props.readerSettings.fontSize}
onChange={handleFontSizeChange}

View file

@ -87,12 +87,12 @@ export const useReaderSettings = (): ReaderSettings => {
switch (action) {
case 'setFontSize':
const value = Number(arg)
if (value >= 10 && value <= 34) {
if (value >= 10 && value <= 48) {
updateFontSize(value)
}
break
case 'incrementFontSize':
updateFontSize(Math.min(fontSize + 2, 34))
updateFontSize(Math.min(fontSize + 2, 48))
break
case 'decrementFontSize':
updateFontSize(Math.max(fontSize - 2, 10))

122
yarn.lock
View file

@ -5981,7 +5981,7 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
"@sindresorhus/is@^4.0.0":
"@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.2.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
@ -11274,7 +11274,7 @@ call-me-maybe@^1.0.1:
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
callsites@^3.0.0:
callsites@^3.0.0, callsites@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
@ -11447,7 +11447,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -13221,6 +13221,11 @@ dezalgo@1.0.3, dezalgo@^1.0.0:
asap "^2.0.0"
wrappy "1"
diacritics@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1"
integrity sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==
diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
@ -13359,6 +13364,15 @@ dom-serializer@^1.0.1:
domhandler "^4.2.0"
entities "^2.0.0"
dom-serializer@^1.3.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
dependencies:
domelementtype "^2.0.1"
domhandler "^4.2.0"
entities "^2.0.0"
dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
@ -13409,7 +13423,7 @@ domhandler@^4.0.0, domhandler@^4.2.0:
dependencies:
domelementtype "^2.2.0"
domhandler@^4.3.1:
domhandler@^4.2.2, domhandler@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
@ -13602,6 +13616,13 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
ejs@^3.1.6:
version "3.1.9"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361"
integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==
dependencies:
jake "^10.8.5"
elastic-ts@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/elastic-ts/-/elastic-ts-0.9.0.tgz#919b7646cd31d753235f3f9a336f7f26c5e3654d"
@ -13750,6 +13771,11 @@ entities@^2.0.0, entities@^2.0.3:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
entities@^3.0.1, entities@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
entities@^4.2.0, entities@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656"
@ -13760,11 +13786,6 @@ entities@~2.1.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
entities@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
env-paths@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@ -13775,6 +13796,25 @@ envinfo@^7.7.3, envinfo@^7.7.4:
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
epub-gen-memory@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/epub-gen-memory/-/epub-gen-memory-1.0.10.tgz#0eef3f1461cb47d982ce48e9e34eb4da69c615fa"
integrity sha512-QS4rEGCO/AUaaofhvAzXAxz0bJ/u23ZGdsdfjVBsWE6LHqM1Mi4R0rs+f6BbGDrHWBvASZkadvrfMc73TFpC6Q==
dependencies:
abort-controller "^3.0.0"
css-select "^4.1.3"
diacritics "^1.3.0"
dom-serializer "^1.3.2"
domhandler "^4.2.2"
domutils "^2.8.0"
ejs "^3.1.6"
htmlparser2 "^7.1.2"
jszip "^3.7.1"
mime "^2.5.2"
node-fetch "^2.0.0"
ow "^0.28.1"
slugify "^1.6.5"
epubjs@^0.3.93:
version "0.3.93"
resolved "https://registry.yarnpkg.com/epubjs/-/epubjs-0.3.93.tgz#100c4597db152fc07d5246be38acca928b6b0b22"
@ -14855,6 +14895,13 @@ file-uri-to-path@1.0.0:
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filelist@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
dependencies:
minimatch "^5.0.1"
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@ -16578,6 +16625,16 @@ htmlparser2@^6.0.0, htmlparser2@^6.1.0:
domutils "^2.5.2"
entities "^2.0.0"
htmlparser2@^7.1.2:
version "7.2.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5"
integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==
dependencies:
domelementtype "^2.0.1"
domhandler "^4.2.2"
domutils "^2.8.0"
entities "^3.0.1"
htmlparser2@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010"
@ -17808,6 +17865,16 @@ jaeger-client@^3.15.0:
uuid "^3.2.1"
xorshift "^0.2.0"
jake@^10.8.5:
version "10.8.7"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f"
integrity sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==
dependencies:
async "^3.2.3"
chalk "^4.0.2"
filelist "^1.0.4"
minimatch "^3.1.2"
jest-changed-files@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5"
@ -19222,6 +19289,11 @@ lodash.isboolean@^3.0.3:
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
lodash.isfunction@^3.0.9:
version "3.0.9"
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051"
@ -20411,7 +20483,7 @@ mime@1.6.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.4.4, mime@^2.5.0:
mime@^2.4.4, mime@^2.5.0, mime@^2.5.2:
version "2.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
@ -20477,7 +20549,7 @@ minimatch@5.0.1:
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1:
minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@ -21101,6 +21173,13 @@ node-fetch@2.6.7, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-
dependencies:
whatwg-url "^5.0.0"
node-fetch@^2.0.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
node-fetch@^2.6.12, node-fetch@^2.6.9:
version "2.6.12"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba"
@ -21864,6 +21943,17 @@ overlayscrollbars@^1.13.1:
resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz#0b840a88737f43a946b9d87875a2f9e421d0338a"
integrity sha512-gIQfzgGgu1wy80EB4/6DaJGHMEGmizq27xHIESrzXq0Y/J0Ay1P3DWk6tuVmEPIZH15zaBlxeEJOqdJKmowHCQ==
ow@^0.28.1:
version "0.28.2"
resolved "https://registry.yarnpkg.com/ow/-/ow-0.28.2.tgz#782b28102124e665c49ec7725e2066a129acf6bf"
integrity sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==
dependencies:
"@sindresorhus/is" "^4.2.0"
callsites "^3.1.0"
dot-prop "^6.0.1"
lodash.isequal "^4.5.0"
vali-date "^1.0.0"
p-all@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0"
@ -25464,6 +25554,11 @@ slide@^1.1.6:
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
slugify@^1.6.5:
version "1.6.6"
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b"
integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==
smart-buffer@^4.1.0, smart-buffer@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
@ -27783,6 +27878,11 @@ v8flags@^2.0.10:
dependencies:
user-home "^1.1.1"
vali-date@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
integrity sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==
valid-url@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"