From 9cb660a0acbe27a1a6ccca7755c6fdeae00c9e55 Mon Sep 17 00:00:00 2001 From: TtiPo Date: Sun, 11 Oct 2026 18:35:11 +0900 Subject: [PATCH] =?UTF-8?q?fix(flutter):=20=EC=B6=94=EC=96=B5=20=EB=B3=B4?= =?UTF-8?q?=EA=B4=80=ED=95=A8=C2=B7=EC=88=9C=EC=84=9C=20=EB=B0=94=EA=BE=B8?= =?UTF-8?q?=EA=B8=B0=EB=8F=84=20=EC=84=9C=EB=B2=84=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=EB=A5=BC=20=EA=B2=AC=EB=94=94=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 서버에 저장하면서 실패할 수 있게 된 남은 흐름을 정리했다. - 보관하기·다시 불러오기는 성공했을 때만 화면을 옮기고 토스트를 띄운다 - 우리 아이 순서 바꾸기는 화면에 먼저 반영하고, 저장하지 못하면 원래 순서로 되돌린다 Co-Authored-By: Claude Opus 5.5 --- .../presentation/pages/archived_pet_page.dart | 2 +- .../pages/pet_archive_move_page.dart | 4 ++-- .../presentation/providers/archive_actions.dart | 16 ++++++++++------ .../presentation/widgets/home_pets_section.dart | 3 ++- .../presentation/providers/pet_providers.dart | 13 ++++++++++--- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/flutter/lib/features/archive/presentation/pages/archived_pet_page.dart b/flutter/lib/features/archive/presentation/pages/archived_pet_page.dart index 32fc77b..fa519f5 100644 --- a/flutter/lib/features/archive/presentation/pages/archived_pet_page.dart +++ b/flutter/lib/features/archive/presentation/pages/archived_pet_page.dart @@ -37,7 +37,7 @@ class ArchivedPetPage extends ConsumerWidget { final String petId; Future _restore(BuildContext context, WidgetRef ref) async { - await ref.read(archiveActionsProvider).restore(petId); + if (!await ref.read(archiveActionsProvider).restore(petId)) return; if (context.mounted) context.go(AppRoutes.archive); } diff --git a/flutter/lib/features/archive/presentation/pages/pet_archive_move_page.dart b/flutter/lib/features/archive/presentation/pages/pet_archive_move_page.dart index f53dab5..5b63664 100644 --- a/flutter/lib/features/archive/presentation/pages/pet_archive_move_page.dart +++ b/flutter/lib/features/archive/presentation/pages/pet_archive_move_page.dart @@ -78,11 +78,11 @@ class _PetArchiveMovePageState extends ConsumerState { Future _submit(Pet pet, DateTime from) async { final memo = _memo.text.trim(); - await ref.read(archiveActionsProvider).archive( + final moved = await ref.read(archiveActionsProvider).archive( pet.id, PetArchive(from: from, to: _to, archivedAt: DateTime.now(), memo: memo.isEmpty ? null : memo), ); - if (mounted) context.go(AppRoutes.myPage); + if (moved && mounted) context.go(AppRoutes.myPage); } @override diff --git a/flutter/lib/features/archive/presentation/providers/archive_actions.dart b/flutter/lib/features/archive/presentation/providers/archive_actions.dart index 281ba2d..e9c2d78 100644 --- a/flutter/lib/features/archive/presentation/providers/archive_actions.dart +++ b/flutter/lib/features/archive/presentation/providers/archive_actions.dart @@ -1,4 +1,5 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:tma_app/core/api/api_guard.dart'; import 'package:tma_app/features/pet/domain/pet_archive.dart'; import 'package:tma_app/features/pet/presentation/providers/pet_providers.dart'; import 'package:tma_app/features/schedule/presentation/providers/schedule_providers.dart'; @@ -11,17 +12,20 @@ class ArchiveActions { final Ref _ref; /// 아이를 보관함으로 옮긴다. 일정은 지우고(여러 아이 일정이면 그 아이만 뗀다), - /// 다이어리·펫 명함·정보는 그대로 두어 보관함에서 다시 볼 수 있게 한다. - Future archive(String petId, PetArchive archive) async { - await _ref.read(petListProvider.notifier).archivePet(petId, archive); + /// 다이어리·펫 명함·정보는 그대로 두어 보관함에서 다시 볼 수 있게 한다 (서버 모드는 일정 정리를 서버가 한다). + /// 옮기지 못하면 false — 실패 알림은 인터셉터가 띄웠다. + Future archive(String petId, PetArchive archive) async { + if (!await succeeded(_ref.read(petListProvider.notifier).archivePet(petId, archive))) return false; await _ref.read(scheduleProvider.notifier).dropTarget(petId); _ref.read(toastProvider.notifier).show('추억보관함에 보관했어요.', tone: ToastTone.memory); + return true; } - /// 보관함에서 다시 불러온다 — 지운 일정은 돌아오지 않는다 - Future restore(String petId) async { - await _ref.read(petListProvider.notifier).restorePet(petId); + /// 보관함에서 다시 불러온다 — 지운 일정은 돌아오지 않는다. 불러오지 못하면 false + Future restore(String petId) async { + if (!await succeeded(_ref.read(petListProvider.notifier).restorePet(petId))) return false; _ref.read(toastProvider.notifier).show('다시 불러왔어요'); + return true; } } diff --git a/flutter/lib/features/home/presentation/widgets/home_pets_section.dart b/flutter/lib/features/home/presentation/widgets/home_pets_section.dart index 4a0e6f9..1e57d31 100644 --- a/flutter/lib/features/home/presentation/widgets/home_pets_section.dart +++ b/flutter/lib/features/home/presentation/widgets/home_pets_section.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import 'package:tma_app/core/api/api_guard.dart'; import 'package:tma_app/core/constants/app_colors.dart'; import 'package:tma_app/core/constants/app_sizes.dart'; import 'package:tma_app/core/router/app_routes.dart'; @@ -57,7 +58,7 @@ class _HomePetsSectionState extends ConsumerState { selectedId: selected?.id, onSelect: (id) => ref.read(selectedPetIdProvider.notifier).select(id), // 꾹 눌러 끌어서 우리 아이 순서를 바꾼다 - onReorder: (ids) => unawaited(ref.read(petListProvider.notifier).reorder(ids)), + onReorder: (ids) => unawaited(succeeded(ref.read(petListProvider.notifier).reorder(ids))), ), if (selected != null) ...[ const SizedBox(height: 20), diff --git a/flutter/lib/features/pet/presentation/providers/pet_providers.dart b/flutter/lib/features/pet/presentation/providers/pet_providers.dart index 58cc699..6b5b141 100644 --- a/flutter/lib/features/pet/presentation/providers/pet_providers.dart +++ b/flutter/lib/features/pet/presentation/providers/pet_providers.dart @@ -39,10 +39,17 @@ class PetListNotifier extends AsyncNotifier> { Future archivePet(String id, PetArchive archive) async => _replace(await _repo.archive(id, archive)); - /// 우리 아이 순서 바꾸기 — 화면에는 바로 반영하고 저장한다 + /// 우리 아이 순서 바꾸기 — 화면에는 바로 반영하고 저장한다. 저장하지 못하면 원래 순서로 되돌린다 Future reorder(List ids) async { - state = AsyncData(reorderPets(state.value ?? const [], ids)); - await _repo.reorder(ids); + final before = state.value ?? const []; + state = AsyncData(reorderPets(before, ids)); + try { + final saved = await _repo.reorder(ids); + if (ref.mounted) state = AsyncData(saved); + } on Exception { + if (ref.mounted) state = AsyncData(before); + rethrow; + } } Future restorePet(String id) async => _replace(await _repo.restore(id));