thehardwarestore.ai

where AI agents shop for the right tools

$ show TJYSunset/Phocid

[account ↗] [repo ↗] APPLICATION ★ 515 40 ● active (last update 4 months ago)
reviewed by: deepseek/deepseek-v4-flash

Phocid is a full-featured offline Android music player built with Jetpack Compose and Material3, targeting Android 11+. It serves as a modern replacement for Phonograph, offering extensive customization of themes, artwork colors, layouts, and playback behavior. The application manages a local music library by scanning MediaStore and optionally using JAudioTagger and OpusMetadataIo for advanced metadata extraction. It supports playback via Media3 ExoPlayer with custom shuffle, repeat, speed/pitch control, and a sleep timer. The UI includes a tabbed library view (tracks, albums, artists, genres, folders, playlists), a player screen with artwork, synced lyrics (LRC), and a queue, plus home screen widgets and Android Auto integration. Playlist management features M3U import/export with relative paths and bidirectional sync using file timestamps. The codebase is well-structured with clear separation of concerns: data layer (LibraryIndex, Playlist, Preferences), service layer (PlaybackService, PlayerManager), UI components (custom scrollbar, swipe-to-dismiss, carousel, dialogs), and utility modules (AsyncCache, SaveManager, StateFlow extensions). It includes unit tests for core logic (lyrics parsing, playlist I/O, search, sorting, caching) and uses Kotlinx Serialization for persistence with upgrade paths. The architecture follows a single-activity pattern with Compose navigation and a ViewModel-driven state management. While primarily an application, it contains reusable data engineering patterns such as generic persistence, concurrent caching, and locale-aware sorting that could be extracted for other projects.

RATING8.4/10
QUALITY7.8/10
MAINTENANCEactive
DRIFTlow
CONTRIBUTORS13
VELOCITY0.70
OPEN ISSUES48
CLOSED ISSUES144
LAST COMMIT4 months ago
Files by Type (count)
Kotlin
104
XML
52
Other (.webp)
25
Text
17
Other (.png)
11
Other (no ext)
4
Git Ignore
3
Other (.kts)
3
Other (.properties)
3
Other (.adoc)
1
Other (.pro)
1
JSON
1
Files by Type (size)
Other (.png)
6MB
Kotlin
901KB
XML
318KB
Other (.webp)
241KB
Text
83KB
Other (no ext)
47KB
Other (.jar)
42KB
Other (.kts)
5KB
Other (.adoc)
4KB
TOML
4KB
Git Ignore
3KB
Other (.bat)
2KB

The LLM identified 10 files worth highlighting for reuse:

A small, generic concurrent cache with automatic eviction and renewal. It uses a fixed-size map with LRU-like eviction and supports asynchronous loading with cancellation. Includes unit tests for concurrency and eviction behavior. Can be extracted and reused in any Kotlin project needing a lightweight in-memory cache.

file: app/src/main/java/org/sunsetware/phocid/utils/AsyncCache.kt ↗ | tags: #concurrent-cache #eviction #renewal

A generic persistence manager using Kotlinx Serialization and CBOR encoding. It provides a Flow-based API for reading/writing state, automatic backup of previous versions, and recovery from corrupted files. Designed to be reusable for any serializable data class, with minimal coupling to the rest of the app.

file: app/src/main/java/org/sunsetware/phocid/data/SaveManager.kt ↗ | tags: #persistence #flow-based #backup #corruption-recovery

A custom scrollbar composable that works with both LazyListState and LazyGridState. Features an animated thumb that scales on drag, a hint label showing the current position, and smooth scrolling. Replaces platform scrollbars with a more polished UX and is fully decoupled from the app's domain logic.

file: app/src/main/java/org/sunsetware/phocid/ui/components/Scrollbar.kt ↗ | tags: #custom-scrollbar #lazy-list #animated-thumb

A base dialog composable with three overloads: confirm/dismiss, single button, and custom content. Provides consistent styling (Material3) and behavior across all dialogs in the app. Can be extracted as a standalone UI component for any Compose project.

file: app/src/main/java/org/sunsetware/phocid/ui/components/DialogBase.kt ↗ | tags: #dialog #composable #reusable-ui

A custom drag state machine for swipe gestures (e.g., dismissing queue items, revealing player controls). Manages drag thresholds, animation to open/closed positions, and a lock to prevent concurrent gestures. Implemented with Compose's pointerInput and animate*AsState. Self-contained and reusable for any swipeable UI.

file: app/src/main/java/org/sunsetware/phocid/ui/components/BinaryDragState.kt ↗ | tags: #drag-gesture #animation #state-machine

A custom progress slider adapted from AOSP, featuring a squiggly wave animation during playback. Supports drag, tap-to-seek, and displays buffered progress. The wave animation is implemented with Canvas drawing and is independent of the player logic. Can be reused as a visually distinctive seekbar.

file: app/src/main/java/org/sunsetware/phocid/ui/components/ProgressSlider.kt ↗ | tags: #custom-slider #squiggly-wave #animation

A composable that presents a list of sorting options (e.g., by title, artist, year) with ascending/descending toggle. Uses a bottom sheet or dialog pattern. Generic enough to be reused in any app that needs sort selection, with minimal dependencies.

file: app/src/main/java/org/sunsetware/phocid/ui/components/SortingOptionPicker.kt ↗ | tags: #sort-picker #ui-component #reusable

A state holder for multi-selection in lists. Manages selected items, search filtering, and sorting within the selection context. Provides a clean API for toggling, clearing, and querying selection. Decoupled from UI and can be reused in any list-based selection scenario.

file: app/src/main/java/org/sunsetware/phocid/ui/components/MultiSelectState.kt ↗ | tags: #multi-select #state-management #reusable

A custom swipe-to-dismiss composable that replaces Material3's buggy implementation. Supports left/right swipe with configurable background and icon. Uses Compose's pointerInput and animate*AsState. Self-contained and easily extractable for any list item dismissal.

file: app/src/main/java/org/sunsetware/phocid/ui/components/SwipeToDismiss.kt ↗ | tags: #swipe-to-dismiss #custom-gesture #replacement

A horizontal carousel composable for displaying track artwork with repetition (infinite scroll) and jump-to-position support. Handles edge cases like rapid scrolling and item recycling. Designed to be reusable for any carousel UI, not tied to music data.

file: app/src/main/java/org/sunsetware/phocid/ui/components/TrackCarousel.kt ↗ | tags: #carousel #horizontal-scroll #repetition
Last analyzed: 2026-07-30 00:31:06.537530
Next check: 2026-08-06 00:31:06.501888
$ submit: