From 795509be1bb1c4c663ce9fc013349b58f252a1ea Mon Sep 17 00:00:00 2001 From: TtiPo Date: Tue, 29 Sep 2026 00:09:09 +0900 Subject: [PATCH] =?UTF-8?q?fix(flutter):=20Riverpod=203.3.2=20=EB=A1=9C=20?= =?UTF-8?q?=EC=98=AC=EB=A6=AC=EA=B3=A0=20=ED=8C=8C=EC=83=9D=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EB=B0=94=EC=9D=B4=EB=8D=94=EA=B0=80=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=EA=B8=B0=EB=A7=8C=20=EB=B3=B4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Riverpod 3 은 가려진 화면의 구독을 멈췄다가 다시 보일 때 빌드 도중에 풀면서 파생값을 다시 계산한다. 3.2.1 에서는 이때 멈춤 횟수 assertion 이 깨졌다 (3.3.2 에서 수정 — pubspec.lock 만 바뀐다). 3.3.2 에도 파생 프로바이더가 다른 파생 프로바이더에 알리면 markNeedsBuild 오류가 나는 경로가 남아 있다. 이를 고친 3.4 는 Dart 3.12 가 필요해 올릴 수 없으므로, 명함·알림의 파생값을 알림기에서 바로 계산하게 바꿔 파생 프로바이더끼리 잇지 않는다. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../presentation/providers/notice_providers.dart | 13 +++++++++---- .../presentation/providers/pet_card_providers.dart | 12 ++++++++---- flutter/pubspec.lock | 8 ++++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/flutter/lib/features/notifications/presentation/providers/notice_providers.dart b/flutter/lib/features/notifications/presentation/providers/notice_providers.dart index 3f1b428..4fefede 100644 --- a/flutter/lib/features/notifications/presentation/providers/notice_providers.dart +++ b/flutter/lib/features/notifications/presentation/providers/notice_providers.dart @@ -5,6 +5,7 @@ import 'package:tma_app/core/storage/preferences_provider.dart'; import 'package:tma_app/core/utils/clock.dart'; import 'package:tma_app/core/utils/date_format.dart'; import 'package:tma_app/features/diary/domain/diary.dart'; +import 'package:tma_app/features/diary/domain/diary_book.dart'; import 'package:tma_app/features/diary/presentation/providers/diary_providers.dart'; import 'package:tma_app/features/mypage/data/app_settings_repository.dart'; import 'package:tma_app/features/notifications/domain/app_notice.dart'; @@ -32,7 +33,11 @@ final noticeSeenProvider = NotifierProvider(Notic /// 모든 다이어리의 알림 — 최근 것이 위로. /// 지금은 기기에서 만드는 기록 알림만 있다. 공유 다이어리의 새 글·댓글은 서버가 생기면 여기에 더한다. -final noticesProvider = Provider>((ref) { +final noticesProvider = Provider>((ref) => _watchNotices(ref)); + +/// 알림 목록을 알림기에서 바로 계산한다 — 파생 프로바이더끼리 이으면 Riverpod 3.3 에서 +/// 가려졌던 화면이 다시 보일 때 빌드 도중 재계산이 번져 markNeedsBuild 오류가 난다 +List _watchNotices(Ref ref) { final now = ref.watch(clockProvider)(); // 저녁 8시·자정에 다시 계산한다 — 앱을 켜 둔 채 시각이 지나도 기록 알림이 맞게 나타나고 사라진다 final next = now.hour < kDiaryReminderHour @@ -45,7 +50,7 @@ final noticesProvider = Provider>((ref) { final settings = ref.watch(appSettingsProvider); if (settings[AppSetting.scheduleNotification] == false) return const []; - final book = ref.watch(diaryBookProvider); + final book = ref.watch(diaryProvider).value ?? DiaryBook.empty; final notices = []; if (now.hour >= kDiaryReminderHour) { final at = DateTime(now.year, now.month, now.day, kDiaryReminderHour); @@ -62,10 +67,10 @@ final noticesProvider = Provider>((ref) { } } return notices..sort((a, b) => b.at.compareTo(a.at)); -}); +} /// 아직 보지 않은 알림이 있는지 — 홈 종에 점을 찍는다 final hasUnreadNoticeProvider = Provider((ref) { final seen = ref.watch(noticeSeenProvider); - return ref.watch(noticesProvider).any((n) => seen == null || n.at.isAfter(seen)); + return _watchNotices(ref).any((n) => seen == null || n.at.isAfter(seen)); }); diff --git a/flutter/lib/features/pet_card/presentation/providers/pet_card_providers.dart b/flutter/lib/features/pet_card/presentation/providers/pet_card_providers.dart index 14e4be4..3128461 100644 --- a/flutter/lib/features/pet_card/presentation/providers/pet_card_providers.dart +++ b/flutter/lib/features/pet_card/presentation/providers/pet_card_providers.dart @@ -78,19 +78,23 @@ class PetCardNotifier extends AsyncNotifier { final petCardsProvider = AsyncNotifierProvider(PetCardNotifier.new); /// 지금 등록된 아이들의 명함만 (지워진 아이의 명함은 숨긴다) -final myCardsProvider = Provider>((ref) { +final myCardsProvider = Provider>((ref) => _watchMyCards(ref)); + +/// 알림기에서 바로 계산한다 — 파생 프로바이더끼리 이으면 Riverpod 3.3 에서 가려졌던 화면이 +/// 다시 보일 때 빌드 도중 재계산이 번져 markNeedsBuild 오류가 난다 +List _watchMyCards(Ref ref) { final cards = ref.watch(petCardsProvider).value?.cards ?? const []; final petIds = {for (final p in ref.watch(petListProvider).value ?? const []) p.id}; return cards.where((c) => petIds.contains(c.petId)).toList(); -}); +} final cardByIdProvider = Provider.family((ref, cardId) { - return ref.watch(myCardsProvider).where((c) => c.id == cardId).firstOrNull; + return _watchMyCards(ref).where((c) => c.id == cardId).firstOrNull; }); /// 아이의 대표 명함 — 지정한 것이 없으면 그 아이의 첫 명함 final representativeCardProvider = Provider.family((ref, petId) { - final cards = ref.watch(myCardsProvider).where((c) => c.petId == petId).toList(); + final cards = _watchMyCards(ref).where((c) => c.petId == petId).toList(); final repId = ref.watch(petCardsProvider).value?.representatives[petId]; return cards.where((c) => c.id == repId).firstOrNull ?? cards.firstOrNull; }); diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 13370a7..4a3e2a4 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -242,10 +242,10 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: "4e166be88e1dbbaa34a280bdb744aeae73b7ef25fdf8db7a3bb776760a3648e2" + sha256: "9255e1e3ad6e38906a1b4f8287678f95f378744c5b46b1985588543f3f19046e" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.3.2" flutter_secure_storage: dependency: "direct main" description: @@ -684,10 +684,10 @@ packages: dependency: transitive description: name: riverpod - sha256: "8c22216be8ad3ef2b44af3a329693558c98eca7b8bd4ef495c92db0bba279f83" + sha256: "17100416c51db7810c71a7bb2c34d1f881faa0074fd452afb0c4db6f8f126c76" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.3.2" share_plus: dependency: "direct main" description: