refactor: extract keyboard navigation handlers into separate methods …#12
Conversation
WalkthroughRefactors Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/Console/Commands/FeedCommand.php (1)
57-57: Replaceenv()withconfig()call.Direct
env()calls are prohibited outside configuration files per the project's coding guidelines. Move this setting to a config file and reference it viaconfig().As per coding guidelines.
For example, add to
config/app.php:'non_interactive' => env('SUPO_NON_INTERACTIVE', false),Then update this line:
-if (env('SUPO_NON_INTERACTIVE', false)) { // @phpstan-ignore-line +if (config('app.non_interactive', false)) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/Console/Commands/FeedCommand.php(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.php
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.php: Use descriptive variable and method names (e.g., isRegisteredForDiscounts)
Always use curly braces for control structures, even single-line
Use PHP 8 constructor property promotion in __construct(); avoid empty constructors
Always use explicit return type declarations for functions and methods
Use appropriate PHP type hints for method parameters
Prefer PHPDoc blocks over inline comments; only comment complex areas
Add useful array shape type definitions in PHPDoc when appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)
Avoid DB::; prefer Model::query() and Eloquent ORM features
Prevent N+1 queries using eager loading
Use query builder for very complex DB operations when needed
Never use env() outside config files; use config() instead
Files:
app/Console/Commands/FeedCommand.php
app/Console/Commands/**/*.php
📄 CodeRabbit inference engine (CLAUDE.md)
Artisan commands in app/Console/Commands auto-register; do not register manually
Console commands in app/Console/Commands auto-register; do not manually register them
Files:
app/Console/Commands/FeedCommand.php
{app,bootstrap,config,database,routes,tests,resources}/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
{app,bootstrap,config,database,routes,tests,resources}/**/*.php: Always use curly braces for PHP control structures, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and do not create empty constructors
Always declare explicit return types for functions/methods and add parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline comments for very complex code
Add useful array shape type definitions in PHPDoc when appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, BestLake, Monthly)
Files:
app/Console/Commands/FeedCommand.php
app/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
app/**/*.php: Prefer Eloquent models/relationships and the query builder over raw queries; avoid DB:: in favor of Model::query()
Prevent N+1 queries using eager loading where necessary
Use Laravel's query builder for very complex DB operations
Use native eager load limiting (e.g., latest()->limit(10)) where applicable
Files:
app/Console/Commands/FeedCommand.php
{app,bootstrap,routes}/**/*.php
📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)
Never call env() outside configuration files; use config() instead (e.g., config('app.name'))
Files:
app/Console/Commands/FeedCommand.php
🧬 Code graph analysis (1)
app/Console/Commands/FeedCommand.php (4)
app/Models/User.php (2)
posts(70-73)User(31-106)app/Actions/LikeAction.php (2)
LikeAction(10-18)handle(12-17)app/Actions/UnlikeAction.php (2)
UnlikeAction(10-16)handle(12-15)app/Console/Commands/EditProfileCommand.php (2)
handle(24-46)EditProfileCommand(17-47)
🔇 Additional comments (1)
app/Console/Commands/FeedCommand.php (1)
70-87: LGTM! Clean extraction improves readability.The refactoring successfully extracts navigation and action handlers while maintaining the original control flow and behavior.
| private function handleNavigateUp(): void | ||
| { | ||
| if ($this->selectedIndex >= 0) { | ||
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block.
Per coding guidelines, prefer PHPDoc blocks for methods. Add documentation explaining the navigation behavior.
As per coding guidelines.
+/**
+ * Navigate up from a post to the header.
+ * Decrements selection index with a lower bound of -3.
+ */
private function handleNavigateUp(): void📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleNavigateUp(): void | |
| { | |
| if ($this->selectedIndex >= 0) { | |
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | |
| } | |
| } | |
| /** | |
| * Navigate up from a post to the header. | |
| * Decrements the selection index with a lower bound of -3. | |
| */ | |
| private function handleNavigateUp(): void | |
| { | |
| if ($this->selectedIndex >= 0) { | |
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | |
| } | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 91 to 96, add a PHPDoc
block for the private method handleNavigateUp() describing its purpose and
behavior: state that it moves the selection up by decrementing
$this->selectedIndex by 1 when the current index is >= 0, with a lower bound of
-3, and include the @return void annotation; keep the doc concise and follow
project PHPDoc style.
| private function handleNavigateDown(Collection $posts): void | ||
| { | ||
| $this->selectedIndex = $this->selectedIndex < 0 ? 0 : min($posts->count() - 1, $this->selectedIndex + 1); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block with parameter documentation.
Per coding guidelines, add PHPDoc describing the method and parameter type.
As per coding guidelines.
+/**
+ * Navigate down to the next post or jump from header to first post.
+ *
+ * @param Collection<int, \App\Models\Post> $posts
+ */
private function handleNavigateDown(Collection $posts): void📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleNavigateDown(Collection $posts): void | |
| { | |
| $this->selectedIndex = $this->selectedIndex < 0 ? 0 : min($posts->count() - 1, $this->selectedIndex + 1); | |
| } | |
| /** | |
| * Navigate down to the next post or jump from header to first post. | |
| * | |
| * @param Collection<int, \App\Models\Post> $posts | |
| */ | |
| private function handleNavigateDown(Collection $posts): void | |
| { | |
| $this->selectedIndex = $this->selectedIndex < 0 ? 0 : min($posts->count() - 1, $this->selectedIndex + 1); | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 98 to 101, the private
method handleNavigateDown lacks a PHPDoc block; add a short PHPDoc comment
immediately above the method with a one-line description of what the method does
and an @param tag documenting the type (\Illuminate\Support\Collection) and
purpose of $posts and an @return void tag to satisfy the coding guidelines.
| private function handleNavigateLeft(): void | ||
| { | ||
| $this->selectedIndex = min(-1, $this->selectedIndex + 1); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block.
As per coding guidelines.
+/**
+ * Navigate left in the header (increment negative index).
+ */
private function handleNavigateLeft(): void📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleNavigateLeft(): void | |
| { | |
| $this->selectedIndex = min(-1, $this->selectedIndex + 1); | |
| } | |
| /** | |
| * Navigate left in the header (increment negative index). | |
| */ | |
| private function handleNavigateLeft(): void | |
| { | |
| $this->selectedIndex = min(-1, $this->selectedIndex + 1); | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 103 to 106, the private
method handleNavigateLeft lacks a PHPDoc block; add a short PHPDoc immediately
above the method with a one-line description (e.g., "Handle navigation to the
left in the feed selection"), include the @return void tag and any relevant tags
(e.g., @access private if you follow that convention), and ensure the doc block
formatting follows project coding guidelines.
| private function handleNavigateRight(): void | ||
| { | ||
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block.
As per coding guidelines.
+/**
+ * Navigate right in the header (decrement negative index).
+ */
private function handleNavigateRight(): void📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleNavigateRight(): void | |
| { | |
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | |
| } | |
| /** | |
| * Navigate right in the header (decrement negative index). | |
| */ | |
| private function handleNavigateRight(): void | |
| { | |
| $this->selectedIndex = max(-3, $this->selectedIndex - 1); | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 108 to 111, the private
method handleNavigateRight is missing a PHPDoc block; add a PHPDoc comment
immediately above the method describing its purpose (e.g., "Move selection to
the right/clamp to minimum index"), include the @return void tag and any
relevant param/behavior notes, and keep it aligned with project docblock style
conventions.
| private function handleToggleLike( | ||
| Collection $posts, | ||
| User $user, | ||
| LikeAction $likeAction, | ||
| UnlikeAction $unlikeAction, | ||
| array $feeds | ||
| ): Collection { | ||
| $post = $posts->all()[$this->selectedIndex]; | ||
| $likedByCurrentUser = $post->likes->contains('user_id', $user->id); | ||
|
|
||
| if ($likedByCurrentUser) { | ||
| $unlikeAction->handle($post, $user); | ||
| } else { | ||
| $likeAction->handle($post, $user); | ||
| } | ||
|
|
||
| return $feeds[$this->activeFeed](); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Extract duplicate like/unlike logic and add PHPDoc.
The like/unlike logic in this method duplicates code in handleEnterKey (lines 145-152). Extract to a shared private method to comply with DRY principles. Also add PHPDoc per coding guidelines.
As per coding guidelines.
Extract the logic:
/**
* Toggle like status for the given post.
*/
private function togglePostLike(Post $post, User $user, LikeAction $likeAction, UnlikeAction $unlikeAction): void
{
$likedByCurrentUser = $post->likes->contains('user_id', $user->id);
if ($likedByCurrentUser) {
$unlikeAction->handle($post, $user);
} else {
$likeAction->handle($post, $user);
}
}Then update both methods:
+/**
+ * Toggle like/unlike for the currently selected post.
+ *
+ * @param Collection<int, \App\Models\Post> $posts
+ * @param array<string, callable(): Collection<int, \App\Models\Post>> $feeds
+ * @return Collection<int, \App\Models\Post>
+ */
private function handleToggleLike(
Collection $posts,
User $user,
LikeAction $likeAction,
UnlikeAction $unlikeAction,
array $feeds
): Collection {
$post = $posts->all()[$this->selectedIndex];
- $likedByCurrentUser = $post->likes->contains('user_id', $user->id);
-
- if ($likedByCurrentUser) {
- $unlikeAction->handle($post, $user);
- } else {
- $likeAction->handle($post, $user);
- }
+ $this->togglePostLike($post, $user, $likeAction, $unlikeAction);
return $feeds[$this->activeFeed]();
}🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 113 to 130, the like/unlike
toggle logic duplicates code also present in handleEnterKey; extract that logic
to a new private method with PHPDoc (e.g., togglePostLike(Post $post, User
$user, LikeAction $likeAction, UnlikeAction $unlikeAction): void) that checks if
$post->likes contains the current user and calls unlikeAction->handle or
likeAction->handle accordingly, then replace the duplicated blocks in both
handleToggleLike and handleEnterKey to call this new private method; ensure the
new method has a one-line PHPDoc summary per coding guidelines and update
affected calls to pass the Post and User and the two action instances.
| private function handleEnterKey( | ||
| Collection $posts, | ||
| User $user, | ||
| LikeAction $likeAction, | ||
| UnlikeAction $unlikeAction, | ||
| array $feeds | ||
| ): Collection { | ||
| if ($this->selectedIndex < 0) { | ||
| $headerIndex = abs($this->selectedIndex) - 1; | ||
| $feedKeys = ['following', 'trending', 'profile']; | ||
| $this->activeFeed = $feedKeys[$headerIndex]; | ||
| $this->scrollOffset = 0; | ||
| } else { | ||
| $post = $posts->all()[$this->selectedIndex]; | ||
| $likedByCurrentUser = $post->likes->contains('user_id', $user->id); | ||
|
|
||
| if ($likedByCurrentUser) { | ||
| $unlikeAction->handle($post, $user); | ||
| } else { | ||
| $likeAction->handle($post, $user); | ||
| } | ||
| } | ||
|
|
||
| return $feeds[$this->activeFeed](); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Add PHPDoc and verify array access safety.
Add PHPDoc per coding guidelines. Also verify that $headerIndex will always be valid (0, 1, or 2) for the $feedKeys array access on line 142.
As per coding guidelines.
+/**
+ * Handle ENTER key: switch feeds in header mode or toggle like on selected post.
+ *
+ * @param Collection<int, \App\Models\Post> $posts
+ * @param array<string, callable(): Collection<int, \App\Models\Post>> $feeds
+ * @return Collection<int, \App\Models\Post>
+ */
private function handleEnterKey(Run the following script to verify that selectedIndex values are always constrained to -3, -2, -1 when in header mode:
🏁 Script executed:
#!/bin/bash
# Verify that header navigation methods constrain selectedIndex to -3, -2, -1
echo "Checking handleNavigateLeft constrains to min -1:"
rg -nP 'handleNavigateLeft.*\{[\s\S]*?selectedIndex.*min\(-1' app/Console/Commands/FeedCommand.php
echo -e "\nChecking handleNavigateRight constrains to max -3:"
rg -nP 'handleNavigateRight.*\{[\s\S]*?selectedIndex.*max\(-3' app/Console/Commands/FeedCommand.php
echo -e "\nChecking handleNavigateUp prevents navigation when in header:"
rg -nP 'handleNavigateUp.*\{[\s\S]*?if.*selectedIndex >= 0' app/Console/Commands/FeedCommand.phpLength of output: 164
I need to examine the navigation methods more carefully to verify the constraints. Let me search for these methods directly.
</script>🏁 Script executed:
#!/bin/bash
# Find and display the navigation methods to verify selectedIndex constraints
echo "=== handleNavigateLeft method ==="
rg -n 'handleNavigateLeft' app/Console/Commands/FeedCommand.php -A 20
echo -e "\n=== handleNavigateRight method ==="
rg -n 'handleNavigateRight' app/Console/Commands/FeedCommand.php -A 20
echo -e "\n=== handleNavigateUp method ==="
rg -n 'handleNavigateUp' app/Console/Commands/FeedCommand.php -A 20
echo -e "\n=== Check for selectedIndex initialization ==="
rg -n 'selectedIndex\s*=' app/Console/Commands/FeedCommand.php | head -20Length of output: 5553
Add PHPDoc to handleEnterKey and DRY duplicate toggle logic
- Add a PHPDoc block on handleEnterKey annotating
Collection<int, App\Models\Post> $posts,User $user,LikeAction,UnlikeAction,array<string, callable():Collection<int, App\Models\Post>> $feeds, and itsCollection<int, App\Models\Post>return. - Extract the duplicated like/unlike handling into a shared method (or call
handleToggleLike) to avoid repeating the toggle logic.
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 132 to 156, add a PHPDoc
block for handleEnterKey annotating Collection<int, App\Models\Post> $posts,
User $user, LikeAction $likeAction, UnlikeAction $unlikeAction, array<string,
callable(): Collection<int, App\Models\Post>> $feeds and a return type of
Collection<int, App\Models\Post>, and refactor the duplicated like/unlike toggle
logic into a single method (e.g. handleToggleLike(User $user, Post $post,
LikeAction $likeAction, UnlikeAction $unlikeAction): void) or call the existing
handleToggleLike so the if/else that checks $post->likes->contains('user_id',
$user->id) is removed from handleEnterKey and replaced by a single call to that
helper.
| private function handleQuit(): void | ||
| { | ||
| outro('See you later!'); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block.
As per coding guidelines.
+/**
+ * Exit the application with a farewell message.
+ */
private function handleQuit(): void📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleQuit(): void | |
| { | |
| outro('See you later!'); | |
| } | |
| /** | |
| * Exit the application with a farewell message. | |
| */ | |
| private function handleQuit(): void | |
| { | |
| outro('See you later!'); | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 158 to 161, the private
method handleQuit() lacks a PHPDoc block; add a short PHPDoc above the method
describing its purpose (e.g., "Display exit message"), include the @return void
tag and note there are no parameters, and keep visibility and signature
unchanged (private function handleQuit(): void). Ensure the PHPDoc follows
project style (/** ... */) and is placed immediately above the method
declaration.
| private function handleEditProfile(array $feeds): Collection | ||
| { | ||
| system('clear'); | ||
| $this->call(EditProfileCommand::class); | ||
|
|
||
| return $feeds[$this->activeFeed](); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add PHPDoc block.
As per coding guidelines.
+/**
+ * Open the profile editor and refresh the feed afterward.
+ *
+ * @param array<string, callable(): Collection<int, \App\Models\Post>> $feeds
+ * @return Collection<int, \App\Models\Post>
+ */
private function handleEditProfile(array $feeds): Collection📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private function handleEditProfile(array $feeds): Collection | |
| { | |
| system('clear'); | |
| $this->call(EditProfileCommand::class); | |
| return $feeds[$this->activeFeed](); | |
| } | |
| /** | |
| * Open the profile editor and refresh the feed afterward. | |
| * | |
| * @param array<string, callable(): Collection<int, \App\Models\Post>> $feeds | |
| * @return Collection<int, \App\Models\Post> | |
| */ | |
| private function handleEditProfile(array $feeds): Collection | |
| { | |
| system('clear'); | |
| $this->call(EditProfileCommand::class); | |
| return $feeds[$this->activeFeed](); | |
| } |
🤖 Prompt for AI Agents
In app/Console/Commands/FeedCommand.php around lines 163 to 169, the private
method handleEditProfile lacks a PHPDoc block; add a concise PHPDoc above the
method describing its purpose, include @param array $feeds and @return
\Illuminate\Support\Collection (or Collection fully-qualified), and any relevant
@throws if applicable, ensuring the doc follows project coding guidelines and
matches the method signature.
Summary
Refactored the
FeedCommandkey press handling logic by extracting inline conditional blocks into dedicated private methods, improving code readability and maintainability.Changes Made
Main Loop Simplification (Lines 68-88)
New Private Methods Added
Navigation Handlers:
handleNavigateUp()– Handles UP arrow and 'k' key (Vim-style navigation)handleNavigateDown()– Handles DOWN arrow and 'j' key (Vim-style navigation)handleNavigateLeft()– Handles LEFT arrow and 'h' key for header navigationhandleNavigateRight()– Handles RIGHT arrow for header navigationAction Handlers:
handleToggleLike()– Toggles like/unlike on the selected post ('l' key)handleEnterKey()– Handles ENTER key (switches feed or toggles like depending on context)handleQuit()– Exits the application ('q' key)handleEditProfile()– Opens the profile editor ('e' key when on profile feed)Benefits
Summary by CodeRabbit