mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-17 15:02:24 +00:00
LibWeb: Rerun find in page query when navigating between URLs
Previously, the "Find Next Match" and "Find Previous Match" actions simply updated the match index of the last query to be performed. This led to incorrect results if the page had been modified after the last query had been run. `Page::find_in_page_next_match()` and `Page::find_in_page_previous_match()` both now rerun the last query to ensure the results are up to date before updating the match index. The match index is also reset if the URL of the active document has changed since the last query. The current match index is maintained if only the URL fragment changes.
This commit is contained in:
parent
077cb7687d
commit
9b5d1382bf
Notes:
sideshowbarker
2024-07-16 23:03:06 +09:00
Author: https://github.com/tcl3
Commit: 9b5d1382bf
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/171
3 changed files with 48 additions and 28 deletions
|
@ -563,19 +563,13 @@ void Page::clear_selection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Page::FindInPageResult Page::find_in_page(String const& query, CaseSensitivity case_sensitivity)
|
Page::FindInPageResult Page::perform_find_in_page_query(FindInPageQuery const& query)
|
||||||
{
|
{
|
||||||
m_find_in_page_match_index = 0;
|
VERIFY(top_level_traversable_is_initialized());
|
||||||
|
|
||||||
if (query.is_empty()) {
|
|
||||||
m_find_in_page_matches = {};
|
|
||||||
update_find_in_page_selection();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<JS::Handle<DOM::Range>> all_matches;
|
Vector<JS::Handle<DOM::Range>> all_matches;
|
||||||
for (auto const& document : documents_in_active_window()) {
|
for (auto const& document : documents_in_active_window()) {
|
||||||
auto matches = document->find_matching_text(query, case_sensitivity);
|
auto matches = document->find_matching_text(query.string, query.case_sensitivity);
|
||||||
all_matches.extend(move(matches));
|
all_matches.extend(move(matches));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,6 +577,15 @@ Page::FindInPageResult Page::find_in_page(String const& query, CaseSensitivity c
|
||||||
for (auto& match : all_matches)
|
for (auto& match : all_matches)
|
||||||
m_find_in_page_matches.append(*match);
|
m_find_in_page_matches.append(*match);
|
||||||
|
|
||||||
|
if (auto active_document = top_level_traversable()->active_document()) {
|
||||||
|
if (m_last_find_in_page_url.serialize(URL::ExcludeFragment::Yes) != active_document->url().serialize(URL::ExcludeFragment::Yes)) {
|
||||||
|
m_last_find_in_page_url = top_level_traversable()->active_document()->url();
|
||||||
|
m_find_in_page_match_index = 0;
|
||||||
|
}
|
||||||
|
} else if (m_find_in_page_match_index >= m_find_in_page_matches.size()) {
|
||||||
|
m_find_in_page_match_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
update_find_in_page_selection();
|
update_find_in_page_selection();
|
||||||
|
|
||||||
return Page::FindInPageResult {
|
return Page::FindInPageResult {
|
||||||
|
@ -591,42 +594,52 @@ Page::FindInPageResult Page::find_in_page(String const& query, CaseSensitivity c
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Page::FindInPageResult Page::find_in_page_next_match()
|
Page::FindInPageResult Page::find_in_page(FindInPageQuery const& query)
|
||||||
{
|
{
|
||||||
if (m_find_in_page_matches.is_empty())
|
if (!top_level_traversable_is_initialized())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (m_find_in_page_match_index == m_find_in_page_matches.size() - 1) {
|
m_find_in_page_match_index = 0;
|
||||||
|
m_last_find_in_page_query = query;
|
||||||
|
m_last_find_in_page_url = top_level_traversable()->active_document()->url();
|
||||||
|
|
||||||
|
if (query.string.is_empty()) {
|
||||||
|
m_last_find_in_page_query = {};
|
||||||
|
update_find_in_page_selection();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_find_in_page_query(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
Page::FindInPageResult Page::find_in_page_next_match()
|
||||||
|
{
|
||||||
|
if (!(m_last_find_in_page_query.has_value() && top_level_traversable_is_initialized()))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto result = perform_find_in_page_query(*m_last_find_in_page_query);
|
||||||
|
if (m_find_in_page_match_index == *result.total_match_count - 1) {
|
||||||
m_find_in_page_match_index = 0;
|
m_find_in_page_match_index = 0;
|
||||||
} else {
|
} else {
|
||||||
m_find_in_page_match_index++;
|
m_find_in_page_match_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_find_in_page_selection();
|
return result;
|
||||||
|
|
||||||
return Page::FindInPageResult {
|
|
||||||
.current_match_index = m_find_in_page_match_index,
|
|
||||||
.total_match_count = m_find_in_page_matches.size(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Page::FindInPageResult Page::find_in_page_previous_match()
|
Page::FindInPageResult Page::find_in_page_previous_match()
|
||||||
{
|
{
|
||||||
if (m_find_in_page_matches.is_empty())
|
if (!(m_last_find_in_page_query.has_value() && top_level_traversable_is_initialized()))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
auto result = perform_find_in_page_query(*m_last_find_in_page_query);
|
||||||
if (m_find_in_page_match_index == 0) {
|
if (m_find_in_page_match_index == 0) {
|
||||||
m_find_in_page_match_index = m_find_in_page_matches.size() - 1;
|
m_find_in_page_match_index = *result.total_match_count - 1;
|
||||||
} else {
|
} else {
|
||||||
m_find_in_page_match_index--;
|
m_find_in_page_match_index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_find_in_page_selection();
|
return result;
|
||||||
|
|
||||||
return Page::FindInPageResult {
|
|
||||||
.current_match_index = m_find_in_page_match_index,
|
|
||||||
.total_match_count = m_find_in_page_matches.size(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Page::update_find_in_page_selection()
|
void Page::update_find_in_page_selection()
|
||||||
|
|
|
@ -187,11 +187,15 @@ public:
|
||||||
|
|
||||||
void clear_selection();
|
void clear_selection();
|
||||||
|
|
||||||
|
struct FindInPageQuery {
|
||||||
|
String string {};
|
||||||
|
CaseSensitivity case_sensitivity { CaseSensitivity::CaseInsensitive };
|
||||||
|
};
|
||||||
struct FindInPageResult {
|
struct FindInPageResult {
|
||||||
size_t current_match_index { 0 };
|
size_t current_match_index { 0 };
|
||||||
Optional<size_t> total_match_count {};
|
Optional<size_t> total_match_count {};
|
||||||
};
|
};
|
||||||
FindInPageResult find_in_page(String const& query, CaseSensitivity);
|
FindInPageResult find_in_page(FindInPageQuery const&);
|
||||||
FindInPageResult find_in_page_next_match();
|
FindInPageResult find_in_page_next_match();
|
||||||
FindInPageResult find_in_page_previous_match();
|
FindInPageResult find_in_page_previous_match();
|
||||||
|
|
||||||
|
@ -203,6 +207,7 @@ private:
|
||||||
|
|
||||||
Vector<JS::Handle<DOM::Document>> documents_in_active_window() const;
|
Vector<JS::Handle<DOM::Document>> documents_in_active_window() const;
|
||||||
|
|
||||||
|
FindInPageResult perform_find_in_page_query(FindInPageQuery const&);
|
||||||
void update_find_in_page_selection();
|
void update_find_in_page_selection();
|
||||||
|
|
||||||
JS::NonnullGCPtr<PageClient> m_client;
|
JS::NonnullGCPtr<PageClient> m_client;
|
||||||
|
@ -248,6 +253,8 @@ private:
|
||||||
bool m_pdf_viewer_supported { false };
|
bool m_pdf_viewer_supported { false };
|
||||||
size_t m_find_in_page_match_index { 0 };
|
size_t m_find_in_page_match_index { 0 };
|
||||||
Vector<JS::NonnullGCPtr<DOM::Range>> m_find_in_page_matches;
|
Vector<JS::NonnullGCPtr<DOM::Range>> m_find_in_page_matches;
|
||||||
|
Optional<FindInPageQuery> m_last_find_in_page_query;
|
||||||
|
URL::URL m_last_find_in_page_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PaintOptions {
|
struct PaintOptions {
|
||||||
|
|
|
@ -812,7 +812,7 @@ void ConnectionFromClient::find_in_page(u64 page_id, String const& query, CaseSe
|
||||||
if (!page.has_value())
|
if (!page.has_value())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto result = page->page().find_in_page(query, case_sensitivity);
|
auto result = page->page().find_in_page({ .string = query, .case_sensitivity = case_sensitivity });
|
||||||
async_did_find_in_page(page_id, result.current_match_index, result.total_match_count);
|
async_did_find_in_page(page_id, result.current_match_index, result.total_match_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue