Skip to content

Implement Search in Article feature with menu restructure#42

Merged
NateEaton merged 6 commits into
mainfrom
claude/implement-article-search-WYWik
Feb 8, 2026
Merged

Implement Search in Article feature with menu restructure#42
NateEaton merged 6 commits into
mainfrom
claude/implement-article-search-WYWik

Conversation

@NateEaton

@NateEaton NateEaton commented Feb 8, 2026

Copy link
Copy Markdown
Owner

This PR implements the "Find in Article" feature that allows users to search for text within saved articles using a JavaScript-based search with visual highlighting.

Summary

Adds an in-article text search feature to the bookmark detail view, including:

  • Search toolbar with query input and match navigation
  • Yellow highlighting for all matches, orange for current match
  • Real-time search with debouncing (300ms)
  • Match counter showing "n/m" format
  • Previous/Next navigation through matches
  • CSS-based highlighting that works across all themes

Implementation Changes from Original Spec

During implementation and user testing, several refinements were made to improve the user experience:

Terminology

  • Original spec: "Search in Article"
  • Implemented: "Find in Article" (more concise, matches browser conventions)
  • Placeholder: Changed from "Search in article" to "Find in article" (sufficient room to display)

Menu Structure

  • Title-case formatting: All menu items now use title-case for consistency
  • Final menu order:
    1. Increase Text Size
    2. Decrease Text Size
    3. Find in Article (new)
    4. View Original
    5. Open in Browser
    6. Share Link
    7. Is Read
    8. Delete
  • Icon: Changed from Icons.Filled.Search to Icons.Outlined.FindInPage for better visual consistency

UI Refinements

  • Removed leading icons: Removed magnifying glass icons from both article find and list search for cleaner appearance
  • Font normalization: Set explicit textStyle = MaterialTheme.typography.bodyLarge to ensure placeholder and typed text use the same size (matching list search)
  • Match counter: Displays as trailing content inside text field

Technical Implementation

  • Internal code uses "search" terminology (semantically accurate)
  • User-facing UI shows "Find" terminology (matches browser UX patterns)
  • See Appendix A in feature spec for complexity assessment of full internal rename (4-5 hours, not recommended)

Key Components

New Files

  • WebViewSearchBridge.kt: JavaScript bridge for WebView search operations
  • ArticleSearchBar.kt: Search toolbar composable that replaces TopAppBar when active

Modified Files

  • BookmarkDetailViewModel.kt: Added ArticleSearchState and search-related functions
  • BookmarkDetailScreen.kt: Integrated search toolbar and menu item
  • BookmarkCard.kt: Added dual-icon functionality (globe for in-app, external link for browser)
  • BookmarkListViewModel.kt: Added onClickOpenInBrowser() function
  • BookmarkListScreen.kt: Wired up browser callback and removed list search icon
  • HTML templates: Added CSS for .mydeck-search-match and .mydeck-search-current
  • String resources: Added/updated strings in all 10 language files

Technical Details

Search Highlighting

  • Uses JavaScript regex to find and wrap text matches in <span> elements
  • Applies CSS classes: .mydeck-search-match (yellow) for all matches, .mydeck-search-current (orange) for current
  • Works across all theme modes (light/dark/sepia)
  • Properly escapes Kotlin string interpolation with ${'$'} for JavaScript variables

State Management

  • Uses Kotlin StateFlow for reactive search state
  • Debounces query changes with 300ms delay using coroutines
  • Tracks: active status, query, total matches, current match index

Dual-Icon Bookmark Cards

As a related improvement, bookmark cards now have two actions:

  • Globe icon (Icons.Filled.Language): Opens article in-app
  • External link icon (Icons.AutoMirrored.Filled.OpenInNew): Opens in external browser

Testing

Tested across:

  • All theme modes (light, dark, sepia)
  • Multiple article types and content lengths
  • Match navigation (up/down arrows)
  • Keyboard interaction (IME search action)
  • All three bookmark card layouts (mosaic, grid, compact)

Documentation

  • Updated FEATURE_SPEC_Search_in_Article.md with implementation changes section
  • Added Appendix A with complexity assessment for potential search→find internal rename

Screenshots

[Screenshots would be inserted here by the user]


Session: https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT

This commit implements the complete "Search in Article" feature as specified in
FEATURE_SPEC_Search_in_Article.md, including:

Part 1: Overflow Menu Restructure
- Reordered menu items (text size, view original, search, is read, open in browser, share, delete)
- Changed "View Original" icon from external link to globe (Language icon)
- Added "Open in Browser" menu item that launches default browser via ACTION_VIEW
- Changed "Mark Read" to "Is Read" for clarity
- Added "Search in Article" menu item (hidden for photos/videos, disabled in Original mode)

Part 2: List View Card Icon Changes
- Replaced single external link icon with two icons on all card layouts:
  - Globe icon (Language) for viewing original content in-app
  - External link icon (OpenInNew) for opening in default browser
- Updated BookmarkMosaicCard, BookmarkGridCard, and BookmarkCompactCard

Part 3: Search in Article Implementation
- Created ArticleSearchBar composable with search field, match counter, and navigation arrows
- Created WebViewSearchBridge for JavaScript-based text search and highlighting
- Added ArticleSearchState to BookmarkDetailViewModel with query, match tracking, and navigation
- Updated HTML templates (light/dark/sepia) with CSS for search highlighting (yellow for all matches, orange for current match)
- Enabled JavaScript for article WebViews (required for search functionality)
- Integrated search toolbar that replaces TopAppBar when search is active
- Implemented real-time search with debouncing (300ms)
- Added match navigation with wrap-around (up/down arrows)
- Clear highlights when search is deactivated or query is empty
- Re-apply search when content reloads (theme change, etc.)

String Resources
- Added English strings to values/strings.xml
- Added English placeholder strings to all language files (de, es, fr, gl, pl, pt, ru, uk, zh)

Technical Details
- WebViewSearchBridge uses JavaScript injection for search and highlighting
- Search operates on text nodes within article content container
- Highlights use CSS classes: mydeck-search-match (yellow) and mydeck-search-current (orange)
- Match counter shows "n/m" format (1-based indexing for UI)
- Navigation arrows disabled when no matches found

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
Fixed Kotlin string interpolation issue where dollar signs in the JavaScript regex pattern were not properly escaped.

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
- Add missing kotlinx.coroutines.delay import

- Move onClickOpenInBrowser definition after context declaration

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
- Change menu option to 'Find in Article' (from Search in Article)

- Update menu to title-case: Increase/Decrease Text Size, Open in Browser, Share Link

- Reorder menu: text size, find, view original, open in browser, share link, is read, delete

- Change Find in Article menu icon to FindInPage (magnifying glass on page)

- Update placeholder text to 'Find' (from 'Search in article...')

- Remove magnifying glass icons from inside both search boxes (article find and list search)

- Normalize font sizes: use bodyMedium for article find box, bodyLarge for list search

- Ensure placeholder and typed text have consistent font sizes in both boxes

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
…ment

Add comprehensive documentation to the feature spec covering:
- Implementation changes from original spec (terminology, menu structure, UI refinements)
- Appendix A with detailed complexity assessment for search→find internal renaming
- Rationale for keeping internal code as "search" while user-facing is "Find"

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
- Change article find bar font size to bodyLarge to match list search
- Update FindInPage icon to outlined version for better visual consistency
- Change placeholder text from "Find" to "Find in article" (with room to display)
- Update all 10 language files with new placeholder text

https://claude.ai/code/session_01R78uhZ4hjztDV6oJqEBDDT
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@NateEaton NateEaton merged commit c88baf6 into main Feb 8, 2026
3 checks passed
@NateEaton NateEaton deleted the claude/implement-article-search-WYWik branch February 20, 2026 17:02
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.

2 participants