Skip to content

Overhaul Compose UI with sidebar navigation and component architecture#48

Merged
linroid merged 7 commits intomainfrom
ui-overhaul
Feb 12, 2026
Merged

Overhaul Compose UI with sidebar navigation and component architecture#48
linroid merged 7 commits intomainfrom
ui-overhaul

Conversation

@linroid
Copy link
Owner

@linroid linroid commented Feb 12, 2026

Summary

  • Restructure monolithic 1,348-line App.kt into 25+ modular components with proper separation of concerns
  • Add left sidebar navigation with status filters (All, Downloading, Paused, Completed, Failed) and live task count badges
  • Introduce custom Material 3 dark/light theme with brand color palette and state-specific colors
  • Add collapsible toggle icons (speed limit, priority, schedule, task info) with animated expandable panels
  • Add bottom status bar showing backend info, connection state, and real-time download speed
  • Extract centralized AppState class for UI state management
  • Add 65 unit tests for format utilities and status filter matching logic
image

Test plan

  • Verify sidebar navigation filters tasks correctly by status
  • Verify collapsible panels expand/collapse properly (only one at a time)
  • Verify dark and light theme switching works
  • Verify status bar shows correct backend info and speeds
  • Run unit tests: ./gradlew :app:shared:allTests
  • Test on Desktop, Android, and Web platforms

🤖 Generated with Claude Code

linroid and others added 4 commits February 12, 2026 11:55
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restructure the monolithic 1,348-line App.kt into a modular component
architecture with proper separation of concerns:

- Add Motrix-style left sidebar navigation with status filters and task counts
- Introduce custom Material 3 dark/light theme with brand color palette
- Extract centralized AppState for UI state management
- Split download list items into composable components (progress, actions, toggles)
- Add collapsible toggle icons for speed limit, priority, schedule, and task info
- Add bottom status bar showing backend info and download speed
- Add comprehensive tests for format utilities and status filter logic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 401b5ea3d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +75
val filteredTasks by remember(
sortedTasks, appState.statusFilter
) {
derivedStateOf {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Recompute filtered task data on state transitions

filteredTasks is wrapped in remember { derivedStateOf { ... } } but the predicate reads taskStates, which is a plain MutableMap and not Compose snapshot state. When a task changes from e.g. Downloading to Completed (without being added/removed), this derived value is not invalidated, so the filtered list (and similarly the count/summary derived blocks below) can stay stale until some unrelated key changes like switching filters.

Useful? React with 👍 / 👎.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex fix it

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Testing

  • curl -I https://developer.android.com/jetpack/compose/state | head
  • ./gradlew :app:shared:allTests (failed: Gradle could not resolve org.gradle.toolchains.foojay-resolver-convention:1.0.0 from configured plugin repositories)

Committed on branch work with commit 75019fb, and I also created the follow-up PR via the make_pr tool.

View task →

Comment on lines +67 to +69
sortedTasks.forEach { task ->
val state by task.state.collectAsState()
taskStates[task.taskId] = state

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prune removed tasks from the cached state map

taskStates only ever inserts/updates entries and never removes IDs that disappeared from sortedTasks. After a task is deleted, its last state remains in the map, so sidebar counts, batch-action visibility, and speed/active aggregates can include tasks that no longer exist.

Useful? React with 👍 / 👎.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex fix it

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Testing

  • ⚠️ ./gradlew :app:shared:allTests (failed in this environment because Gradle could not resolve org.gradle.toolchains.foojay-resolver-convention:1.0.0 from configured plugin repositories).
  • curl -I https://plugins.gradle.org/m2/ (web check executed successfully).

View task →

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Test Results

978 tests  +222   978 ✅ +222   12s ⏱️ ±0s
 69 suites +  6     0 💤 ±  0 
 69 files   +  6     0 ❌ ±  0 

Results for commit fd0770e. ± Comparison against base commit eebc6a9.

♻️ This comment has been updated with latest results.

linroid and others added 3 commits February 12, 2026 13:32
- Include Idle state in Downloading filter so sub-counts sum to All
- Use mutableStateMapOf for reactive task state tracking and clean stale entries
- Use Card onClick instead of Modifier.clickable for proper ripple clipping
- Reorder sidebar filters: All, Downloading, Completed, Paused, Failed
- Add copy-to-clipboard button on URL row in task info panel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Calculate bytesPerSecond in DownloadCoordinator.buildContext using
elapsed time delta (sampled every 500ms) and pass it to DownloadProgress.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace four independent AnimatedVisibility blocks with a single
AnimatedContent keyed on the expanded panel enum, so panel transitions
crossfade smoothly without intermediate height changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@linroid linroid merged commit fd8ba1c into main Feb 12, 2026
@linroid linroid deleted the ui-overhaul branch February 12, 2026 08:52
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.

1 participant