20260309 #51 todo list screen 캘린더 중심 재설계#52
Conversation
- flutter_slidable 패키지 추가 - 좌→우: 카테고리 이동, 우→좌: 날짜 제거 + 삭제 - CustomSlidableAction으로 반투명 배경 + 아이콘/텍스트 스타일 적용
- todosNotForDate provider 추가 (선택 날짜에 미배정 할일 필터) - 홈 화면에 '할 일 추가' 섹션으로 todo bank 표시 - 탭하면 해당 날짜에 즉시 배정
- Slidable context 분리 (slidableContext vs buildContext) - deleteTodo에 await 추가하여 에러 시 rollback 정상 작동 - 마지막 배정 날짜 제거 시 확인 다이얼로그 추가 - addDateToTodo를 TodoListNotifier로 이동 + 중복 날짜 체크 - 날짜 정규화를 TodoEntity.normalizeDate()로 통일 - TodoEntity.studyTimeLabel getter로 subtitle 중복 제거 - SizedBox(height: 4.h) → AppSpacing.s4
Walkthrough홈 화면에 할당되지 않은 할일을 보여주는 Todo Bank를 추가하고 Dismissible을 Slidable로 교체해 좌/우 스와이프 액션(카테고리 이동, 날짜 제거, 삭제)을 도입했습니다. provider에 Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant Home as HomeScreen
participant Slidable as Slidable Widget
participant TodoProv as TodoProvider
participant DB as 데이터베이스
User->>Home: 홈 진입 및 날짜 선택
Home->>TodoProv: todosNotForDate(selectedDate) 요청
TodoProv->>DB: 미할당 할일 조회
DB-->>TodoProv: 미할당 할일 반환
TodoProv-->>Home: 미할당 할일 전달 (Todo Bank 표시)
rect rgba(100,150,200,0.5)
User->>Home: Todo Bank 항목 탭 (할일 추가)
Home->>TodoProv: addDateToTodo(todo, date)
TodoProv->>DB: todo.scheduledDates에 정규화된 날짜 추가
DB-->>TodoProv: 저장 완료
TodoProv-->>Home: 상태 갱신
end
rect rgba(200,150,100,0.5)
User->>Slidable: 할일 좌/우 스와이프
Slidable->>Home: 액션 트리거 (카테고리 이동/날짜 제거/삭제)
Home->>TodoProv: 해당 업데이트 요청
TodoProv->>DB: 변경 저장/삭제
DB-->>TodoProv: 완료
TodoProv-->>Home: UI 갱신
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 4
🧹 Nitpick comments (1)
lib/features/home/presentation/screens/home_screen.dart (1)
513-515: 새 bank row 패딩은 AppPadding preset으로 맞춰 주세요.여기서 다시
EdgeInsets.fromLTRB(...)를 쓰면 리스트 행 간격 규칙이 파일마다 흩어집니다.AppPadding.listItemPadding같은 preset을 쓰거나 필요한 preset을 상수로 추가하는 편이 맞습니다.As per coding guidelines
Never hardcode padding — use AppPadding presets (all, horizontal, vertical) and specialized presets (screenPadding, cardPadding, listItemPadding, buttonPadding) from core/constants/app_padding.dart.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/features/home/presentation/screens/home_screen.dart` around lines 513 - 515, The Padding around the TodoItem in HomeScreen uses a hardcoded EdgeInsets.fromLTRB which violates the no-hardcode-padding rule; replace that with the AppPadding preset (e.g., AppPadding.listItemPadding) or add a new preset in core/constants/app_padding.dart if one doesn’t exist, then use that preset for the Padding around TodoItem to keep list row spacing consistent across files.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/features/home/presentation/screens/home_screen.dart`:
- Around line 435-436: The empty-state message is shown even when there are bank
items available; update the rendering in home_screen.dart so the empty-state
card is only shown when both the selected date's todos are empty AND the
todo-bank is empty, otherwise render the todo-bank section
(_buildTodoBankSection(selectedKey)) above or instead of the empty state;
alternatively, if you prefer to keep the empty-state visible when bank exists,
change its copy to a date-scoped message like "이 날짜에 배정된 할 일이 없어요" to avoid
suggesting adding via + when bank items are available.
- Around line 498-500: The Home screen is directly coupled to todo presentation
providers — replace direct uses of todosNotForDateProvider and
todoListNotifierProvider in _buildTodoBankSection and _addTodoToDate with a
domain/application-level abstraction (e.g., a TodoUseCase or HomeTodoFacade
provider) that exposes only the required methods/data (e.g.,
fetchTodosNotForDate(selectedDate) and addTodoToDate(todo, date)); update calls
to use ref.watch/ref.read of that new facade instead of
todosNotForDateProvider/todoListNotifierProvider so the home presentation only
depends on the domain/application abstraction per the Clean 3-Layer guideline
and dependency inversion.
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 100-104: The onToggle currently computes date = contextDate ??
DateTime.now() and calls toggleTodoForDate(todo, date), causing a mismatch when
contextDate is null; change this to either (A) disable toggling when contextDate
== null by returning early from the onToggle handler so the UI and mutation
align, or (B) add a dedicated global toggle mutation on the notifier (e.g.,
toggleTodoGlobal(Todo todo)) and call
ref.read(todoListNotifierProvider.notifier).toggleTodoGlobal(todo) when
contextDate == null so the mutation uses the same global completion semantics as
the UI; update the onToggle branch in dismissible_todo_item.dart to check
contextDate and call the appropriate path.
- Around line 233-236: The _isLinkedToTimer function in
dismissible_todo_item.dart directly reads timerNotifierProvider (timerState) and
thus couples the todo presentation to timer presentation; instead remove this
direct provider read and accept the linkage as an injected dependency (either a
boolean parameter like isLinkedToTimer on the DismissibleTodoItem widget or an
abstracted domain/service interface such as TodoTimerLinker.isLinked(todo.id)
provided by the parent). Update the parent that constructs DismissibleTodoItem
to compute the flag (e.g., watch timerNotifierProvider there or use the domain
abstraction) and pass it down, or register and inject the domain-level
abstraction through providers so _isLinkedToTimer is eliminated and the widget
no longer calls timerNotifierProvider directly.
---
Nitpick comments:
In `@lib/features/home/presentation/screens/home_screen.dart`:
- Around line 513-515: The Padding around the TodoItem in HomeScreen uses a
hardcoded EdgeInsets.fromLTRB which violates the no-hardcode-padding rule;
replace that with the AppPadding preset (e.g., AppPadding.listItemPadding) or
add a new preset in core/constants/app_padding.dart if one doesn’t exist, then
use that preset for the Padding around TodoItem to keep list row spacing
consistent across files.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cab9b651-8267-47ec-874f-659cd44832dc
⛔ Files ignored due to path filters (1)
pubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (12)
docs/plans/2026-03-09-todo-list-calendar-redesign.mdlib/features/auth/presentation/providers/auth_provider.g.dartlib/features/badge/presentation/providers/badge_provider.g.dartlib/features/exploration/presentation/providers/exploration_provider.g.dartlib/features/home/presentation/screens/home_screen.dartlib/features/settings/presentation/providers/settings_provider.g.dartlib/features/timer/presentation/providers/timer_provider.g.dartlib/features/todo/domain/entities/todo_entity.dartlib/features/todo/presentation/providers/todo_provider.dartlib/features/todo/presentation/providers/todo_provider.g.dartlib/features/todo/presentation/widgets/dismissible_todo_item.dartpubspec.yaml
| final todosNotForDate = ref.watch( | ||
| todosNotForDateProvider(selectedDate), | ||
| ); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
홈 화면이 todo presentation provider에 직접 결합돼 있습니다.
_buildTodoBankSection와 _addTodoToDate가 todosNotForDateProvider/todoListNotifierProvider를 바로 읽으면서 home feature가 todo feature의 presentation layer를 알아야 합니다. 이 읽기/쓰기 경로는 domain/usecase나 상위 application provider 뒤로 숨겨서 화면은 그 추상화만 보게 하는 편이 경계가 덜 새어 나갑니다.
As per coding guidelines Use Clean 3-Layer Architecture with Dependency Inversion Principle (Presentation → Domain ← Data) — Domain layer must be at the center and reverse dependencies are forbidden.
Also applies to: 535-536
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/features/home/presentation/screens/home_screen.dart` around lines 498 -
500, The Home screen is directly coupled to todo presentation providers —
replace direct uses of todosNotForDateProvider and todoListNotifierProvider in
_buildTodoBankSection and _addTodoToDate with a domain/application-level
abstraction (e.g., a TodoUseCase or HomeTodoFacade provider) that exposes only
the required methods/data (e.g., fetchTodosNotForDate(selectedDate) and
addTodoToDate(todo, date)); update calls to use ref.watch/ref.read of that new
facade instead of todosNotForDateProvider/todoListNotifierProvider so the home
presentation only depends on the domain/application abstraction per the Clean
3-Layer guideline and dependency inversion.
lib/features/todo/presentation/widgets/dismissible_todo_item.dart
Outdated
Show resolved
Hide resolved
| bool _isLinkedToTimer(WidgetRef ref) { | ||
| final timerState = ref.read(timerNotifierProvider); | ||
| return timerState.status != TimerStatus.idle && | ||
| timerState.linkedTodoId == todo.id; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
todo 위젯이 timer presentation provider를 직접 읽고 있습니다.
_isLinkedToTimer가 timerNotifierProvider를 바로 읽으면서 todo presentation이 timer presentation에 결합됐습니다. 이 플래그는 상위에서 주입하거나 domain/application 레벨의 추상화로 노출하는 편이 기능 경계를 지키기 쉽습니다.
As per coding guidelines Use Clean 3-Layer Architecture with Dependency Inversion Principle (Presentation → Domain ← Data) — Domain layer must be at the center and reverse dependencies are forbidden.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart` around
lines 233 - 236, The _isLinkedToTimer function in dismissible_todo_item.dart
directly reads timerNotifierProvider (timerState) and thus couples the todo
presentation to timer presentation; instead remove this direct provider read and
accept the linkage as an injected dependency (either a boolean parameter like
isLinkedToTimer on the DismissibleTodoItem widget or an abstracted
domain/service interface such as TodoTimerLinker.isLinked(todo.id) provided by
the parent). Update the parent that constructs DismissibleTodoItem to compute
the flag (e.g., watch timerNotifierProvider there or use the domain abstraction)
and pass it down, or register and inject the domain-level abstraction through
providers so _isLinkedToTimer is eliminated and the widget no longer calls
timerNotifierProvider directly.
- bank에 할일이 있으면 빈 상태 카드 숨기고 bank만 표시 - 불필요한 Consumer 래핑 제거 (상위에서 watch한 데이터 전달) - contextDate null일 때 토글 no-op 처리하여 표시/저장 기준 불일치 해결
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
lib/features/todo/presentation/widgets/dismissible_todo_item.dart (1)
53-56: Slidable 액션 배경색도 AppColors 경로로 통일해 주세요.세 곳 모두
Colors.transparent를 직접 넣고 있어서 이 파일만 색상 예외 규칙이 생깁니다. 필요하면 transparent 토큰을AppColors에 추가해서라도 한 경로로 맞추는 편이 좋습니다.As per coding guidelines
Never hardcode colors — use AppColors constants from core/constants/app_colors.dart.Also applies to: 72-75, 82-85
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart` around lines 53 - 56, Replace the three hardcoded Colors.transparent usages in this file (used as backgroundColor for CustomSlidableAction instances) with the AppColors token from core/constants/app_colors.dart (e.g., AppColors.transparent); if AppColors does not yet expose a transparent token, add one there first and then import and use it in dismissible_todo_item.dart so all Slidable actions (including the ones tied to _moveCategory and the other two CustomSlidableAction calls) use the centralized AppColors constant instead of a hardcoded color.lib/features/home/presentation/screens/home_screen.dart (1)
512-513: bank 항목 패딩도 AppPadding 토큰으로 통일해 주세요.여기서 새
EdgeInsets.fromLTRB(20.w, 0, 20.w, AppSpacing.s8)를 만들면 같은 화면 안에서도 padding 규칙이 다시 갈라집니다. 이미 위에서 쓰는 preset처럼AppPadding기반으로 맞추는 편이 낫습니다.As per coding guidelines
Never hardcode padding — use AppPadding presets (all, horizontal, vertical) and specialized presets (screenPadding, cardPadding, listItemPadding, buttonPadding) from core/constants/app_padding.dart.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/features/home/presentation/screens/home_screen.dart` around lines 512 - 513, Replace the hardcoded EdgeInsets.fromLTRB(20.w, 0, 20.w, AppSpacing.s8) used in the bank item Padding with the AppPadding preset and then add the bottom spacing; e.g. use AppPadding.horizontal.add(EdgeInsets.only(bottom: AppSpacing.s8)) (or the appropriate AppPadding preset like screenPadding if that better matches the surrounding presets) so the bank item's padding follows the shared AppPadding tokens instead of a hardcoded EdgeInsets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/features/home/presentation/screens/home_screen.dart`:
- Around line 523-524: 함수 _addTodoToDate를 void에서 Future<void>로 변경하고 내부에서
addDateToTodo 비동기 호출을 await로 수행한 뒤 try-catch로 에러를 잡아 사용자 피드백(예: 스낵바/토스트/로깅)을
호출하도록 수정하세요; 또한 이 헬퍼를 호출하는 곳(onToggle/onTap 익명 콜백)도 async로 바꾸고 await
_addTodoToDate(ref, todo, selectedDate)로 호출하도록 업데이트해 비동기 실패가 누락되지 않게 하세요.
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 150-154: The calls to updateTodo (in the branch that sets
categoryIds and the other location that updates categories) must be awaited and
error-handled: change
ref.read(todoListNotifierProvider.notifier).updateTodo(...) to await the call,
wrap it in try { await updateTodo(...) } catch (e, st) { if (context.mounted)
ScaffoldMessenger.of(context).showSnackBar(...) } matching the pattern used in
removeDateFromTodo/deleteTodo so failures surface to the user; ensure you
preserve context.mounted checks before showing the SnackBar and keep the same
notifier method signature (updateTodo) and todo.copyWith(...) usage.
---
Nitpick comments:
In `@lib/features/home/presentation/screens/home_screen.dart`:
- Around line 512-513: Replace the hardcoded EdgeInsets.fromLTRB(20.w, 0, 20.w,
AppSpacing.s8) used in the bank item Padding with the AppPadding preset and then
add the bottom spacing; e.g. use
AppPadding.horizontal.add(EdgeInsets.only(bottom: AppSpacing.s8)) (or the
appropriate AppPadding preset like screenPadding if that better matches the
surrounding presets) so the bank item's padding follows the shared AppPadding
tokens instead of a hardcoded EdgeInsets.
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 53-56: Replace the three hardcoded Colors.transparent usages in
this file (used as backgroundColor for CustomSlidableAction instances) with the
AppColors token from core/constants/app_colors.dart (e.g.,
AppColors.transparent); if AppColors does not yet expose a transparent token,
add one there first and then import and use it in dismissible_todo_item.dart so
all Slidable actions (including the ones tied to _moveCategory and the other two
CustomSlidableAction calls) use the centralized AppColors constant instead of a
hardcoded color.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f4c96349-2418-4316-b49c-ae82933f0827
📒 Files selected for processing (2)
lib/features/home/presentation/screens/home_screen.dartlib/features/todo/presentation/widgets/dismissible_todo_item.dart
| onToggle: () => _addTodoToDate(ref, todo, selectedDate), | ||
| onTap: () => _addTodoToDate(ref, todo, selectedDate), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find the home_screen.dart file and check its size
fd -t f "home_screen.dart" lib/features/home/presentation/screens/
# Then read the relevant sectionsRepository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 131
🏁 Script executed:
# Get the file location and inspect lines around 523-524 and 532-534
cat -n lib/features/home/presentation/screens/home_screen.dart | sed -n '515,545p'Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 1222
🏁 Script executed:
# Also search for the _addTodoToDate method definition
grep -n "_addTodoToDate" lib/features/home/presentation/screens/home_screen.dartRepository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 297
🏁 Script executed:
# Search for the addDateToTodo mutation definition to verify it's async
grep -n "addDateToTodo" lib/features/home/presentation/screens/home_screen.dart | head -20Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 154
🏁 Script executed:
# Find the todoListNotifierProvider
fd -t f "todo_list.*provider" lib/features/home/Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 58
🏁 Script executed:
# Search for todoListNotifierProvider definition
rg "todoListNotifierProvider" lib/features/home/ -A 5 | head -40Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 1237
🏁 Script executed:
# Search for addDateToTodo method definition
rg "addDateToTodo" lib/features/home/ -B 3 -A 10Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 1270
🏁 Script executed:
# Search across entire lib directory for todoListNotifierProvider
rg "final todoListNotifierProvider" lib/ -A 10Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 1117
🏁 Script executed:
# Search for the notifier class that has addDateToTodo method
rg "class.*Notifier.*extends" lib/features/home/ -A 20 | grep -A 20 "TodoList\|addDateToTodo"Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 58
🏁 Script executed:
# Find all provider files in home feature
fd -t f "provider" lib/features/home/Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 58
🏁 Script executed:
# List all files in home presentation directory
ls -la lib/features/home/presentation/Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 296
🏁 Script executed:
# Find the source provider file (not generated)
fd -t f "todo_provider.dart" lib/features/todo/Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 135
🏁 Script executed:
# Read the TodoListNotifier class implementation
rg "class TodoListNotifier" lib/features/todo/ -A 100 | head -150Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 9215
🏁 Script executed:
# Search specifically for addDateToTodo method
rg "addDateToTodo" lib/features/todo/ -B 3 -A 15Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 1747
🏁 Script executed:
# Check if there are other usages of _addTodoToDate at lines around 532-534
cat -n lib/features/home/presentation/screens/home_screen.dart | sed -n '525,540p'Repository: SpaceStudyShip/SpaceStudyShip-FE
Length of output: 550
_addTodoToDate()를 Future<void>로 변경하고 await/try-catch로 에러 처리 필수
addDateToTodo()가 비동기 mutation인데 _addTodoToDate()가 void 반환형이고 await 없이 호출되므로, 저장 실패 시 에러가 처리되지 않은 채 비동기로 흘러갑니다. 이 헬퍼를 Future<void>로 변경하고 내부에서 await/try-catch로 사용자 피드백을 처리해 주세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/features/home/presentation/screens/home_screen.dart` around lines 523 -
524, 함수 _addTodoToDate를 void에서 Future<void>로 변경하고 내부에서 addDateToTodo 비동기 호출을
await로 수행한 뒤 try-catch로 에러를 잡아 사용자 피드백(예: 스낵바/토스트/로깅)을 호출하도록 수정하세요; 또한 이 헬퍼를
호출하는 곳(onToggle/onTap 익명 콜백)도 async로 바꾸고 await _addTodoToDate(ref, todo,
selectedDate)로 호출하도록 업데이트해 비동기 실패가 누락되지 않게 하세요.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/features/todo/presentation/widgets/dismissible_todo_item.dart (1)
218-229:⚠️ Potential issue | 🟡 Minor
_openEditSheet의updateTodo()호출에도 동일한 에러 핸들링이 필요합니다.
_moveCategory와 마찬가지로, 할일 수정 저장 실패 시 사용자에게 피드백을 제공해야 합니다.🛡️ 에러 핸들링 추가 제안
if (result != null && context.mounted) { - await ref - .read(todoListNotifierProvider.notifier) - .updateTodo( - todo.copyWith( - title: result['title'] as String, - categoryIds: (result['categoryIds'] as List<String>?) ?? [], - scheduledDates: - (result['scheduledDates'] as List<DateTime>?) ?? [], - ), - ); + try { + await ref + .read(todoListNotifierProvider.notifier) + .updateTodo( + todo.copyWith( + title: result['title'] as String, + categoryIds: (result['categoryIds'] as List<String>?) ?? [], + scheduledDates: + (result['scheduledDates'] as List<DateTime>?) ?? [], + ), + ); + } catch (e) { + if (context.mounted) { + AppSnackBar.error(context, '할일 수정에 실패했습니다'); + } + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart` around lines 218 - 229, The call to updateTodo inside _openEditSheet needs the same error handling as _moveCategory: wrap the await ref.read(todoListNotifierProvider.notifier).updateTodo(...) in a try/catch, catch and log the exception, and present user feedback (e.g., ScaffoldMessenger.of(context).showSnackBar or an error dialog) only if context.mounted; keep using todo.copyWith(...) for the update payload and ensure any caught error does not crash the UI.
♻️ Duplicate comments (1)
lib/features/todo/presentation/widgets/dismissible_todo_item.dart (1)
12-13: 🛠️ Refactor suggestion | 🟠 Majortodo presentation이 timer presentation을 직접 import하고 있습니다.
timerNotifierProvider와TimerState를 직접 import하여_isLinkedToTimer메서드에서 사용하고 있어, todo feature가 timer feature의 presentation 레이어에 결합됩니다.이전 리뷰에서도 언급되었듯이, 이 의존성은 상위 위젯에서
isLinkedToTimerboolean 파라미터로 주입하거나 domain 레벨의 추상화를 통해 제공하는 것이 Clean Architecture 원칙에 부합합니다.As per coding guidelines:
Use Clean 3-Layer Architecture with Dependency Inversion Principle (Presentation → Domain ← Data) — Domain layer must be at the center and reverse dependencies are forbidden.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart` around lines 12 - 13, The DismissibleTodoItem widget currently imports timerNotifierProvider and TimerState and uses them in _isLinkedToTimer, coupling todo presentation to timer presentation; remove the direct imports and stop using timerNotifierProvider/TimerState inside _isLinkedToTimer, instead accept an injected boolean (e.g., isLinkedToTimer) on the DismissibleTodoItem constructor or obtain linkage via a domain-level abstraction passed in (e.g., an ITaskTimerLinkChecker interface) and update _isLinkedToTimer to use that injected value/method; ensure all callers (parent widgets) pass the isLinkedToTimer boolean or the domain abstraction rather than letting the todo widget depend on timer presentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 150-154: The call to updateTodo (via
ref.read(todoListNotifierProvider.notifier).updateTodo) is awaited but lacks
error handling; wrap that await in a try-catch like the patterns used in
_removeFromDate and _deleteTodo, catch and log the exception, and show user
feedback (e.g., Snackbar/ScaffoldMessenger or the same feedback helper used
elsewhere) if the update fails; ensure you still check context.mounted before
showing UI feedback and keep the existing newCategoryIds null check.
---
Outside diff comments:
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 218-229: The call to updateTodo inside _openEditSheet needs the
same error handling as _moveCategory: wrap the await
ref.read(todoListNotifierProvider.notifier).updateTodo(...) in a try/catch,
catch and log the exception, and present user feedback (e.g.,
ScaffoldMessenger.of(context).showSnackBar or an error dialog) only if
context.mounted; keep using todo.copyWith(...) for the update payload and ensure
any caught error does not crash the UI.
---
Duplicate comments:
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart`:
- Around line 12-13: The DismissibleTodoItem widget currently imports
timerNotifierProvider and TimerState and uses them in _isLinkedToTimer, coupling
todo presentation to timer presentation; remove the direct imports and stop
using timerNotifierProvider/TimerState inside _isLinkedToTimer, instead accept
an injected boolean (e.g., isLinkedToTimer) on the DismissibleTodoItem
constructor or obtain linkage via a domain-level abstraction passed in (e.g., an
ITaskTimerLinkChecker interface) and update _isLinkedToTimer to use that
injected value/method; ensure all callers (parent widgets) pass the
isLinkedToTimer boolean or the domain abstraction rather than letting the todo
widget depend on timer presentation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e02f04bb-ccb1-4d93-8c5c-bc26dcc95c71
📒 Files selected for processing (2)
lib/features/home/presentation/screens/home_screen.dartlib/features/todo/presentation/widgets/dismissible_todo_item.dart
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/features/home/presentation/screens/home_screen.dart
| if (newCategoryIds != null && context.mounted) { | ||
| await ref | ||
| .read(todoListNotifierProvider.notifier) | ||
| .updateTodo(todo.copyWith(categoryIds: newCategoryIds)); | ||
| } |
There was a problem hiding this comment.
updateTodo() 호출에 에러 핸들링을 추가하세요.
await가 추가되었지만, _removeFromDate나 _deleteTodo의 패턴처럼 try-catch로 감싸서 실패 시 사용자에게 피드백을 제공해야 합니다.
🛡️ 에러 핸들링 추가 제안
if (newCategoryIds != null && context.mounted) {
- await ref
- .read(todoListNotifierProvider.notifier)
- .updateTodo(todo.copyWith(categoryIds: newCategoryIds));
+ try {
+ await ref
+ .read(todoListNotifierProvider.notifier)
+ .updateTodo(todo.copyWith(categoryIds: newCategoryIds));
+ } catch (e) {
+ if (context.mounted) {
+ AppSnackBar.error(context, '카테고리 변경에 실패했습니다');
+ }
+ }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/features/todo/presentation/widgets/dismissible_todo_item.dart` around
lines 150 - 154, The call to updateTodo (via
ref.read(todoListNotifierProvider.notifier).updateTodo) is awaited but lacks
error handling; wrap that await in a try-catch like the patterns used in
_removeFromDate and _deleteTodo, catch and log the exception, and show user
feedback (e.g., Snackbar/ScaffoldMessenger or the same feedback helper used
elsewhere) if the update fails; ensure you still check context.mounted before
showing UI feedback and keep the existing newCategoryIds null check.
✨ 변경 사항
✅ 테스트
Summary by CodeRabbit
새로운 기능
개선 사항