Merge pull request #3009 from omnivore-app/fix/ios-force-pdf-reading-position

Force reading position to update on iOS in PDFs
This commit is contained in:
Jackson Harper 2023-10-25 09:21:43 +08:00 committed by GitHub
commit 6443da0afc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 757 additions and 712 deletions

View file

@ -237,13 +237,12 @@ import Utils
let pageIndex = Int(event.pageIndex)
if let totalPageCount = controller.document?.pageCount {
let percent = min(100, max(0, ((Double(pageIndex) + 1.0) / Double(totalPageCount)) * 100.0))
if percent > self.viewModel.pdfItem.readingProgress {
self.viewModel.updateItemReadProgress(
dataService: dataService,
percent: percent,
anchorIndex: pageIndex
)
}
self.viewModel.updateItemReadProgress(
dataService: dataService,
percent: percent,
anchorIndex: pageIndex,
force: true
)
}
}
}.store(in: &subscriptions)

View file

@ -76,11 +76,12 @@ final class PDFViewerViewModel: ObservableObject {
}
}
func updateItemReadProgress(dataService: DataService, percent: Double, anchorIndex: Int) {
func updateItemReadProgress(dataService: DataService, percent: Double, anchorIndex: Int, force: Bool = false) {
dataService.updateLinkReadingProgress(
itemID: pdfItem.itemID,
readingProgress: percent,
anchorIndex: anchorIndex
anchorIndex: anchorIndex,
force: force
)
}

View file

@ -356,34 +356,11 @@ import Views
}
func markRead(dataService: DataService, item: LinkedItem) {
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 100, anchorIndex: 0)
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 100, anchorIndex: 0, force: true)
}
func markUnread(dataService: DataService, item: LinkedItem) {
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0)
}
func snoozeUntil(dataService: DataService, linkId: String, until: Date, successMessage: String?) async {
isLoading = true
if let itemIndex = items.firstIndex(where: { $0.id == linkId }) {
items.remove(at: itemIndex)
}
do {
try await dataService.createReminder(
reminderItemId: .link(id: linkId),
remindAt: until
)
if let message = successMessage {
snackbar(message)
}
} catch {
NSNotification.operationFailed(message: "Failed to snooze")
}
isLoading = false
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0, force: true)
}
private var queryContainsFilter: Bool {

View file

@ -39,7 +39,8 @@ import Views
dataService.updateLinkReadingProgress(
itemID: itemID,
readingProgress: isItemRead ? 0 : 100,
anchorIndex: 0
anchorIndex: 0,
force: false
)
}

View file

@ -233,7 +233,7 @@ struct WebReaderContainerView: View {
)
Button(
action: {
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0)
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0, force: true)
},
label: { Label("Reset Read Location", systemImage: "arrow.counterclockwise.circle") }
)
@ -432,7 +432,7 @@ struct WebReaderContainerView: View {
#endif
.onAppear {
if item.isUnread {
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0.1, anchorIndex: 0)
dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0.1, anchorIndex: 0, force: false)
}
Task {
await audioController.preload(itemIDs: [item.unwrappedID])

View file

@ -171,7 +171,7 @@ struct SafariWebLink: Identifiable {
return
}
dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: readingProgress, anchorIndex: anchorIndex)
dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: readingProgress, anchorIndex: anchorIndex, force: false)
replyHandler(["result": true], nil)
}

View file

@ -740,7 +740,7 @@
let anchorIndex = Int((player?.currentItem as? SpeechPlayerItem)?.speechItem.htmlIdx ?? "") ?? 0
if let itemID = itemAudioProperties?.itemID {
dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: percentProgress, anchorIndex: anchorIndex)
dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: percentProgress, anchorIndex: anchorIndex, force: true)
}
if let itemID = itemAudioProperties?.itemID, let player = player, let currentItem = player.currentItem {

File diff suppressed because it is too large Load diff

View file

@ -1,79 +1 @@
import Foundation
import Models
import SwiftGraphQL
public enum ReminderItemId {
case clientRequest(id: String)
case link(id: String)
var linkId: String? {
switch self {
case .clientRequest:
return nil
case let .link(id):
return id
}
}
var clientRequestId: String? {
switch self {
case .link:
return nil
case let .clientRequest(id):
return id
}
}
}
public extension DataService {
func createReminder(
reminderItemId: ReminderItemId,
remindAt: Date
) async throws {
enum MutationResult {
case complete(id: String)
case error(errorCode: Enums.CreateReminderErrorCode)
}
let selection = Selection<MutationResult, Unions.CreateReminderResult> {
try $0.on(
createReminderError: .init { .error(errorCode: try $0.errorCodes().first ?? .badRequest) },
createReminderSuccess: .init {
.complete(id: try $0.reminder(selection: Selection.Reminder { try $0.id() }))
}
)
}
let mutation = Selection.Mutation {
try $0.createReminder(
input: InputObjects.CreateReminderInput(
archiveUntil: true,
clientRequestId: OptionalArgument(reminderItemId.clientRequestId),
linkId: OptionalArgument(reminderItemId.linkId),
remindAt: DateTime(from: remindAt),
sendNotification: true
),
selection: selection
)
}
let path = appEnvironment.graphqlPath
let headers = networker.defaultHeaders
return try await withCheckedThrowingContinuation { continuation in
send(mutation, to: path, headers: headers) { queryResult in
guard let payload = try? queryResult.get() else {
continuation.resume(throwing: BasicError.message(messageText: "network error"))
return
}
switch payload.data {
case .complete:
continuation.resume()
case let .error(errorCode: errorCode):
continuation.resume(throwing: BasicError.message(messageText: errorCode.rawValue))
}
}
}
}
}

View file

@ -4,13 +4,15 @@ import Models
import SwiftGraphQL
extension DataService {
public func updateLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int) {
public func updateLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int, force: Bool?) {
backgroundContext.perform { [weak self] in
guard let self = self else { return }
guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { return }
if readingProgress != 0, readingProgress < linkedItem.readingProgress {
return
if let force = force, !force {
if readingProgress != 0, readingProgress < linkedItem.readingProgress {
return
}
}
print("updating reading progress: ", readingProgress, anchorIndex)
@ -24,12 +26,13 @@ extension DataService {
self.syncLinkReadingProgress(
itemID: linkedItem.unwrappedID,
readingProgress: readingProgress,
anchorIndex: anchorIndex
anchorIndex: anchorIndex,
force: force
)
}
}
func syncLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int) {
func syncLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int, force: Bool?) {
enum MutationResult {
case saved(readAt: Date?)
case error(errorCode: Enums.SaveArticleReadingProgressErrorCode)
@ -49,8 +52,9 @@ extension DataService {
let mutation = Selection.Mutation {
try $0.saveArticleReadingProgress(
input: InputObjects.SaveArticleReadingProgressInput(
force: OptionalArgument(force),
id: itemID,
readingProgressAnchorIndex: anchorIndex,
readingProgressAnchorIndex: OptionalArgument(anchorIndex),
readingProgressPercent: readingProgress
),
selection: selection

View file

@ -154,7 +154,8 @@ public extension DataService {
syncLinkReadingProgress(
itemID: item.unwrappedID,
readingProgress: item.readingProgress,
anchorIndex: Int(item.readingProgressAnchor)
anchorIndex: Int(item.readingProgressAnchor),
force: item.isPDF
)
}
}

View file

@ -26,7 +26,7 @@ extension DataService {
createdAt: try $0.createdAt().value ?? Date(),
savedAt: try $0.savedAt().value ?? Date(),
readAt: try $0.readAt()?.value,
updatedAt: try $0.updatedAt().value ?? Date(),
updatedAt: try $0.updatedAt()?.value ?? Date(),
state: try $0.state()?.rawValue.asArticleContentStatus ?? .succeeded,
readingProgress: try $0.readingProgressPercent(),
readingProgressAnchor: try $0.readingProgressAnchorIndex(),

View file

@ -258,7 +258,7 @@ private let libraryArticleSelection = Selection.Article {
createdAt: try $0.createdAt().value ?? Date(),
savedAt: try $0.savedAt().value ?? Date(),
readAt: try $0.readAt()?.value,
updatedAt: try $0.updatedAt().value ?? Date(),
updatedAt: try $0.updatedAt()?.value ?? Date(),
state: try $0.state()?.rawValue.asArticleContentStatus ?? .succeeded,
readingProgress: try $0.readingProgressPercent(),
readingProgressAnchor: try $0.readingProgressAnchorIndex(),

View file

@ -19,7 +19,7 @@ public extension DataService {
status: try SubscriptionStatus.make(from: $0.status()),
unsubscribeHttpUrl: try $0.unsubscribeHttpUrl(),
unsubscribeMailTo: try $0.unsubscribeMailTo(),
updatedAt: try $0.updatedAt().value,
updatedAt: try $0.updatedAt()?.value ?? Date(),
url: try $0.url(),
icon: try $0.icon()
)

View file

@ -1,3 +1,4 @@
import Foundation
import Models
import SwiftGraphQL
@ -22,7 +23,7 @@ let highlightSelection = Selection.Highlight {
patch: try $0.patch() ?? "",
annotation: try $0.annotation(),
createdAt: try $0.createdAt().value,
updatedAt: try $0.updatedAt().value,
updatedAt: try $0.updatedAt()?.value ?? Date(),
createdByMe: try $0.createdByMe(),
createdBy: try $0.user(selection: userProfileSelection),
positionPercent: try $0.highlightPositionPercent(),