$ show FooIbar/EhViewer
EhViewer is a high-performance Android client for browsing, reading, and downloading galleries from the E-Hentai / ExHentai image hosting sites. It is a modern fork of the classic EhViewer app, built entirely with Kotlin Multiplatform for shared logic and Jetpack Compose with Material Design 3 for the UI. The architecture is modular (app, core/common, core/data, core/ui, core/i18n) and leverages Rust via JNI for performance-critical HTML parsing and image processing (border detection, QR code detection, WebP animation). The app features a full-featured reader with multiple reading modes, a foreground download service with speed tracking, comprehensive offline support via Room/SQLite, and integration with GitHub releases for updates. The codebase is actively maintained, uses the latest Kotlin, Compose, and Ktor versions, and demonstrates strong engineering practices with clean abstractions, coroutine-based reactive state, and type-safe preferences. It is a dedicated application project with no data science or research components.
The LLM identified 3 files worth highlighting for reuse:
A generic set of closed ranges (`IntRange`) implemented with an array-backed sorted list and binary search for efficient insertion, removal, and containment checks. It supports iteration and is completely self-contained (no Android dependencies). This is a reusable utility for any Kotlin project that needs to track intervals, such as download progress, pagination, or selection ranges.
A lightweight speed tracker that uses exponential moving average to smooth download speed measurements. It provides current speed, average speed, and estimated time remaining. The implementation is clean, dependency-free, and can be reused in any application that needs to monitor transfer rates (e.g., downloads, uploads, streaming).
A suspend-based dialog API for Jetpack Compose that allows calling code to show dialogs (input, confirmation, selection, date/time picker) and await user input directly from coroutines, avoiding complex state management. The implementation uses `DialogState` and `Composable` lambdas, and is structured so that it can be extracted as a reusable pattern for any Compose application needing coroutine-driven dialogs.