Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwiftUI: Open a book on tap #240

Open
wants to merge 10 commits into
base: swiftui
Choose a base branch
from

Conversation

gatamar
Copy link
Contributor

@gatamar gatamar commented Sep 3, 2022

This PR aims to open a book somehow.

Changes:

  • extracted new services BookOpener, BookImporter , BookRemover from the LibraryService
  • added a wrapper over the ReaderViewController
  • improved navigation - when we open a book, a bottom tab bar disappears
  • refactored Container, as now it has more responsibilities

Out of scope (coming soon in the next PRs):

  • Highlights, Search, and any other Reader supporting views

@gatamar gatamar temporarily deployed to LCP September 3, 2022 23:34 Inactive
@mickael-menu mickael-menu changed the title Open a book on tap SwiftUI: Open a book on tap Sep 16, 2022
Copy link
Member

@mickael-menu mickael-menu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @gatamar, I left a few comments already but didn't have time to review everything yet.

TestApp/Sources/Swiftui/Services/BookOpener.swift Outdated Show resolved Hide resolved
Comment on lines 13 to 19
class BookOpener: ObservableObject, Loggable {
@Published var openedBookPublication: Publication?
@Published var openedBook: Book?
@Published var openedBookTag: Book.Id?
@Published var curOpeningBookId: Book.Id?

init(readerDependencies: ReaderDependencies) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an actor for BookOpener will make sure that any async function called on it will be run from a background thread and not block the UI. This will be useful when accessing the files on the file system for example.

The nonisolated keyword on init is to avoid needing to call await BookOpener() when creating the BookOpener.

Suggested change
class BookOpener: ObservableObject, Loggable {
@Published var openedBookPublication: Publication?
@Published var openedBook: Book?
@Published var openedBookTag: Book.Id?
@Published var curOpeningBookId: Book.Id?
init(readerDependencies: ReaderDependencies) {
actor BookOpener: ObservableObject, Loggable {
@Published var openedBookPublication: Publication?
@Published var openedBook: Book?
@Published var openedBookTag: Book.Id?
@Published var curOpeningBookId: Book.Id?
nonisolated init(readerDependencies: ReaderDependencies) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added the actor declaration. For the nonisolated, it seems it's already deprecated :)
Screenshot 2022-10-03 at 20 20 24

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha interesting, and you don't need to spawn a Task to call the initializer without nonisolated?

TestApp/Sources/Swiftui/Views/NewReaderView.swift Outdated Show resolved Hide resolved
TestApp/Sources/Swiftui/Views/NewReaderView.swift Outdated Show resolved Hide resolved
Comment on lines 25 to 28
NavigationLink(
destination: readerView(),
tag: book.id!,
selection: self.$bookOpener.openedBookTag
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SwiftUI Navigation API pre iOS 16 is really not great :/ We need to create the destination view for all the covers and the bookshelf has to know how to create the reader views.

I suggest we migrate to the iOS 16 NavigationStack to move this responsibility outside of the Bookshelf view:

Here we have a situation which is a bit special because we have an async task that is run before changing the stack, so I think that NavigationLink is not very convenient as it is synchronous. Instead we could use a simple button to start the task, and use the programmatic navigation using a @State variable as explained here:
https://developer.apple.com/documentation/swiftui/navigationlink#Control-a-presentation-link-programmatically

That might be a bit complicated and out of scope for this PR. Maybe for now you could just present the reader outside of the NavigationView when it's ready using .fullScreenCover()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickael-menu Thank you for the guidance!
Regarding iOS 16 API, I think NavigationPath fits for our purposes (it's closely related to the NavigationStack).
More details:

I've added a basic version (no tasks cancellation added yet), please check if this API looks good to you.

@gatamar gatamar temporarily deployed to LCP October 3, 2022 18:42 Inactive
@gatamar gatamar temporarily deployed to LCP October 10, 2022 22:22 Inactive
…ort sheet UI, as it's already added, there're just serious issues with navigation
@mickael-menu mickael-menu temporarily deployed to LCP May 23, 2023 14:50 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants