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

Add user interface to search through a publication #164

Closed
mickael-menu opened this issue May 17, 2021 · 11 comments
Closed

Add user interface to search through a publication #164

mickael-menu opened this issue May 17, 2021 · 11 comments

Comments

@mickael-menu
Copy link
Member

mickael-menu commented May 17, 2021

(Please respond in this issue if you want to contribute this feature and have any question)

The PR readium/r2-shared-swift#135 adds a new SearchService feature to search through the content of a publication. We need to expose this in the user interface of the test app.

Here are some general guidelines:

  • SearchService is described in this proposal.
  • The search interface needs to be added for the ReaderViewController if publication.isSearchable is true.
  • It would be best to load the next page of results (iterator.next() when scrolling to the end of the results table view)

Starting a search

To start a new search, use publication.search(). It will asynchronously return a SearchIterator if the search is valid. This iterator can be used to get the search results.

let cancellable = publication.search(query: "banana") { result in
    switch result {
        case .success(let iterator):
            // show results using iterator
        case .failure(let error):
            // display error
    }
}

Showing the results

The results will be displayed in a table view. Every time the user scrolls to the end of the scroll view, you need to request the next page of results with iterator.next(). It will return a LocatorCollection, or nil if the search is finished.

let cancellable = iterator.next { result in
    switch result {
        case .success(let collection):
            if let collection = collection {
                // append `collection.locators` to the table view
            } else {
                // search is finished
            }
        case .failure(let error):
            // display error
    }
}

For each Locator cell:

  • If locator.title is different from the previous locator.title, create a new section with this title in the table view
  • Display the locator.locations.totalProgression in the cell
  • Display the search snippet with locator.text.before + locator.text.highlight + locator.text.after, putting emphasis on the locator.text.highlight portion.

Cancelling the search

When the user cancels the search, you need to dispose of the search properly:

  • If publication.search() didn't return an iterator yet, call cancel() on the Cancellable returned by publication.search().
  • If a SearchIterator was received:
    • call cancel() on the Cancellable returned by the last iterator.next() call
    • call iterator.close()
@newit-toannv
Copy link

simulator_screenshot_436D6911-40F1-40EE-864D-21475495FFED

@newit-toannv
Copy link

newit-toannv commented Jul 2, 2021

The first time search, results always in same title, not full tableview

@mickael-menu
Copy link
Member Author

Thanks @newit-toannv! Maybe you can open a pull request so we can discuss the implementation there?

@mickael-menu
Copy link
Member Author

To get more results you need to call iterator.next() until the screen is filled or there are no more results.

@newit-toannv
Copy link

newit-toannv commented Jul 6, 2021 via email

@mickael-menu
Copy link
Member Author

Yeah that's because the search API returns a flat list of Locator, there's no concept of hierarchy/tree for sections.

What you need to do is create a new section in the table view every time you have a different locator.title in the list. This way it will group the locator by their title in order.

@newit-toannv
Copy link

newit-toannv commented Jul 7, 2021 via email

@mickael-menu
Copy link
Member Author

I think the best way to represent that would be to use actual UITableView sections for this. Less work and it will look nicer in the UI.

@JacobDaneh
Copy link

Hi,
Thank you for implementing search service. search service has good performance.
How could i highlight text in the epub when user taps search result and navigating to the selected location?

SearchService.mov

@mickael-menu
Copy link
Member Author

How could i highlight text in the epub when user taps search result and navigating to the selected location?

You can use the new Decorator API that is available in Readium Swift 2.1.

It should look something like that (I didn't check the exact syntax):

let searchLocator = ...
let searchIndex = ...

let decoration = Decoration(
    // The index in the search result list is a suitable Decoration ID, as long as
    // we clear the search decorations between two searches.
    id: searchIndex,
    locator: searchLocator,
    style: .underline()
)

navigator.apply(decorations: [decoration], in: "search")

@mickael-menu
Copy link
Member Author

I gave more details in this discussion: https://github.com/readium/r2-testapp-swift/discussions/402

@mickael-menu mickael-menu transferred this issue from readium/r2-testapp-swift Aug 12, 2022
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

No branches or pull requests

3 participants