@@ -64,24 +64,18 @@ struct ArchiveAlbumDetailFeature {
6464 case onTapDuplicateButton
6565 case onTapMoveButton
6666 case albumSelection( PresentationAction < AlbumSelectionFeature . Action > )
67- case duplicatePhotosResponse( Result < Void , Error > )
68- case movePhotosResponse( Result < Void , Error > )
6967
7068 case onTapDownloadButton
7169 case downloadImagesResponse( successCount: Int )
7270
73- // 사진 삭제 액션
7471 case onTapDeleteButton( option: ArchivePhotoDeleteOption )
7572 case deletePhotosResponse( Result < Void , Error > )
7673
77- // 앨범 삭제 액션
7874 case onTapExecuteDeleteAlbum( option: ArchiveAlbumDeleteOption )
7975 case deleteAlbumResponse( Result < Void , Error > )
8076
81- // 사진 가져오기 액션
8277 case onTapImportPhotos
8378 case photoImport( PresentationAction < PhotoImportFeature . Action > )
84- case importPhotosResponse( Result < Void , Error > )
8579
8680 case fetchPhotos
8781 case photoListResponse( Result < [ PhotoEntity ] , Error > )
@@ -107,17 +101,13 @@ struct ArchiveAlbumDetailFeature {
107101 Reduce { state, action in
108102 switch action {
109103 case . onTapBackButton: return . run { _ in await dismiss ( ) }
110-
111104 case . onAppear: return . send( . fetchPhotos)
112-
113105 case . toggleDropDownMenu:
114106 state. showDropDownMenu. toggle ( )
115107 return . none
116-
117108 case . closeDropDownMenu:
118109 state. showDropDownMenu = false
119110 return . none
120-
121111 case let . onTapFavorite( item) :
122112 let newStatus = !item. isFavorite
123113 state. photos [ id: item. id] ? . isFavorite = newStatus
@@ -129,23 +119,18 @@ struct ArchiveAlbumDetailFeature {
129119 await send ( . toggleFavoriteResponse( photoID: id, result: . failure( error) ) )
130120 }
131121 }
132-
133122 case . toggleFavoriteResponse( _, . success) : return . none
134-
135123 case let . toggleFavoriteResponse( photoID, . failure) :
136124 state. photos [ id: photoID] ? . isFavorite. toggle ( )
137125 return . send( . delegate( . showToast( NekiToastItem ( " 즐겨찾기 변경에 실패했어요 " , style: . error) ) ) )
138-
139126 case let . imagePicker( . delegate( . imagesConverted( entities) ) ) :
140127 state. showDropDownMenu = false
141128 return . send( . processUploadImages( entities: entities) )
142-
143129 case let . processUploadImages( entities) :
144130 state. isLoading = false
145131 guard !entities. isEmpty else { return . none }
146132 state. isLoading = true
147133 return . send( . registerPhotos( entities: entities) )
148-
149134 case let . registerPhotos( entities) :
150135 let albumId = state. album. id
151136 return . run { send in
@@ -155,43 +140,35 @@ struct ArchiveAlbumDetailFeature {
155140 try await archiveClient. registerPhotos ( folderId: albumId, uploads: uploads , favorite: false )
156141 } ) )
157142 }
158-
159143 case . registerPhotosResponse( . success) :
160144 state. isLoading = false
161145 return . run { send in
162146 await send ( . delegate( . showToast( NekiToastItem ( " 이미지를 추가했어요 " , style: . success) ) ) )
163147 await send ( . fetchPhotos)
164148 }
165-
166149 case . registerPhotosResponse( . failure) :
167150 state. isLoading = false
168151 return . send( . delegate( . showToast( NekiToastItem ( " 업로드에 실패했어요 " , style: . error) ) ) )
169-
170152 case . onTapCancelEditAlbum:
171153 state. newAlbumTitle = state. album. title
172154 state. albumTitleErrorMessage = nil
173155 return . none
174-
175156 case . onTapConfirmEditAlbum:
176157 guard state. isConfirmButtonEnabled else { return . none }
177158 let title = state. newAlbumTitle. trimmingCharacters ( in: . whitespacesAndNewlines)
178159 state. albumTitleErrorMessage = nil
179160 return . run { [ albumId = state. album. id] send in
180161 await send ( . editAlbumResponse( Result { try await archiveClient. editAlbumName ( albumId, title) } ) )
181162 }
182-
183163 case . editAlbumResponse( . success) : return . send( . delegate( . showToast( NekiToastItem ( " 앨범 이름을 변경했어요 " , style: . success) ) ) )
184-
185164 case . editAlbumResponse( . failure) :
186165 state. newAlbumTitle = state. album. title
187166 return . send( . delegate( . showToast( NekiToastItem ( " 앨범 이름을 변경하지 못했어요 " , style: . error) ) ) )
188-
189167 case . fetchPhotos:
190168 state. isFetchingPhotos = true
191169 return . run { [ albumId = state. album. id] send in
192170 await send ( . photoListResponse( Result { try await archiveClient. fetchPhotoList ( folderId: albumId, size: 20 , sortOrder: nil ) } ) )
193171 }
194-
195172 case let . photoListResponse( . success( entities) ) :
196173 state. isFetchingPhotos = false
197174 let currentAlbumId = state. album. id
@@ -200,110 +177,60 @@ struct ArchiveAlbumDetailFeature {
200177 }
201178 state. photos = IdentifiedArray ( uniqueElements: newItems)
202179 return . none
203-
204180 case . photoListResponse( . failure) :
205181 state. isFetchingPhotos = false
206182 return . send( . delegate( . showToast( NekiToastItem ( " 사진을 불러오지 못했어요 " , style: . error) ) ) )
207-
208183 case . loadMorePhotos: return . send( . fetchPhotos)
209-
210184 case . onTapSelectButton:
211185 state. showDropDownMenu = false
212186 state. isSelectionMode = true
213187 return . none
214-
215188 case . onTapCancelSelectButton:
216189 state. isSelectionMode = false
217190 state. selectedIDs. removeAll ( )
218191 return . none
219-
220192 case let . imageTapped( item) :
221193 if state. isSelectionMode {
222194 if state. selectedIDs. contains ( item. id) { state. selectedIDs. remove ( item. id) }
223195 else { state. selectedIDs. insert ( item. id) }
224196 }
225197 return . none
226-
227198 case . onTapDuplicateButton:
228- state. selectionPurpose = . duplicate
229- state. albumSelection = AlbumSelectionFeature . State ( uploadCount: state. selectedIDs. count, selectionPurpose: . duplicate, currentAlbumId: state. album. id)
199+ state. albumSelection = AlbumSelectionFeature . State ( photoIDs: Array ( state. selectedIDs) , selectionPurpose: . duplicate, currentAlbumId: state. album. id)
230200 return . none
231-
232201 case . onTapMoveButton:
233- state. selectionPurpose = . move
234- state. albumSelection = AlbumSelectionFeature . State ( uploadCount: state. selectedIDs. count, selectionPurpose: . move, currentAlbumId: state. album. id)
202+ state. albumSelection = AlbumSelectionFeature . State ( photoIDs: Array ( state. selectedIDs) , selectionPurpose: . move, currentAlbumId: state. album. id)
235203 return . none
236-
237204 case let . albumSelection( . presented( . delegate( delegateAction) ) ) :
238205 switch delegateAction {
239- case let . didSelectAlbums( albumIds) :
240- let purpose = state. selectionPurpose
241-
206+ case let . didCompleteTask( message) :
242207 state. albumSelection = nil
243- state. selectionPurpose = nil
244- state. isLoading = true
245-
246- return . run { send in
247- if purpose == . duplicate {
248- // TODO: API 붙이기
249- try ? await Task . sleep ( for: . seconds( 1 ) ) // 테스트용 임시 딜레이
250- await send ( . duplicatePhotosResponse( . success( ( ) ) ) )
251- } else {
252- // TODO: API 붙이기
253- try ? await Task . sleep ( for: . seconds( 1 ) ) // 테스트용 임시 딜레이
254- await send ( . movePhotosResponse( . success( ( ) ) ) )
255- }
256- }
257-
208+ state. isSelectionMode = false
209+ state. selectedIDs. removeAll ( )
210+ return . merge(
211+ . send( . delegate( . showToast( NekiToastItem ( message, style: . success) ) ) ) ,
212+ . send( . fetchPhotos)
213+ )
258214 case . didTapCancel:
259215 state. albumSelection = nil
260- state. selectionPurpose = nil
261216 return . none
262-
263217 case let . showToast( toastItem) :
264218 return . send( . delegate( . showToast( toastItem) ) )
265219 }
266-
267- case . duplicatePhotosResponse( . success) :
268- state. isLoading = false
269- state. isSelectionMode = false
270- state. selectedIDs. removeAll ( )
271- return . send( . delegate( . showToast( NekiToastItem ( " 사진을 앨범에 추가했어요 " , style: . success) ) ) )
272-
273- case . duplicatePhotosResponse( . failure) :
274- state. isLoading = false
275- return . send( . delegate( . showToast( NekiToastItem ( " 사진 추가에 실패했어요 " , style: . error) ) ) )
276-
277- case . movePhotosResponse( . success) :
278- state. isLoading = false
279- state. isSelectionMode = false
280- state. selectedIDs. removeAll ( )
281- return . merge(
282- . send( . delegate( . showToast( NekiToastItem ( " 사진을 앨범으로 이동했어요 " , style: . success) ) ) ) ,
283- . send( . fetchPhotos)
284- )
285-
286- case . movePhotosResponse( . failure) :
287- state. isLoading = false
288- return . send( . delegate( . showToast( NekiToastItem ( " 사진 이동에 실패했어요 " , style: . error) ) ) )
289-
290220 case . onTapDownloadButton:
291221 guard !state. selectedIDs. isEmpty else { return . none }
292222 state. isLoading = true
293223 return . run { [ photos = state. photos, selectedIDs = state. selectedIDs] send in
294224 let urls = selectedIDs. compactMap { photos [ id: $0] ? . imageURL }
295-
296225 let count = try await imageDownloadClient. downloadImages ( urls: urls)
297226 await send ( . downloadImagesResponse( successCount: count) )
298227 }
299-
300228 case let . downloadImagesResponse( count) :
301229 state. isLoading = false
302230 state. isSelectionMode = false
303231 state. selectedIDs. removeAll ( )
304232 if count > 0 { return . send( . delegate( . showToast( NekiToastItem ( " 사진을 갤러리에 다운로드했어요 " , style: . success) ) ) ) }
305233 else { return . send( . delegate( . showToast( NekiToastItem ( " 사진 저장에 실패했어요 " , style: . error) ) ) ) }
306-
307234 case let . onTapDeleteButton( option) :
308235 guard !state. selectedIDs. isEmpty else { return . none }
309236 let selectedIDs = Array ( state. selectedIDs)
@@ -314,17 +241,14 @@ struct ArchiveAlbumDetailFeature {
314241 else { try await archiveClient. deletePhotoList ( selectedIDs) }
315242 } ) )
316243 }
317-
318244 case . deletePhotosResponse( . success) :
319245 let idsToDelete = state. selectedIDs
320246 state. photos. removeAll { idsToDelete. contains ( $0. id) }
321247 state. isSelectionMode = false
322248 state. selectedIDs. removeAll ( )
323249 return . send( . delegate( . showToast( NekiToastItem ( " 사진을 삭제했어요 " , style: . success) ) ) )
324-
325250 case . deletePhotosResponse( . failure) :
326251 return . send( . delegate( . showToast( NekiToastItem ( " 사진을 삭제하지 못했어요 " , style: . error) ) ) )
327-
328252 case let . onTapExecuteDeleteAlbum( option) :
329253 let shouldDeletePhotos = ( option == . withPhotos)
330254 let albumId = state. album. id
@@ -333,49 +257,36 @@ struct ArchiveAlbumDetailFeature {
333257 try await archiveClient. deleteFolders ( [ albumId] , shouldDeletePhotos)
334258 } ) )
335259 }
336-
337260 case . deleteAlbumResponse( . success) :
338261 return . run { send in
339262 await send ( . delegate( . showToast( NekiToastItem ( " 앨범을 삭제했어요 " , style: . success) ) ) )
340263 await dismiss ( )
341264 }
342-
343265 case . deleteAlbumResponse( . failure) :
344266 return . send( . delegate( . showToast( NekiToastItem ( " 앨범을 삭제하지 못했어요 " , style: . error) ) ) )
345267
346268 case . onTapImportPhotos:
347269 state. showDropDownMenu = false
348- state. photoImport = PhotoImportFeature . State ( )
270+ state. photoImport = PhotoImportFeature . State ( targetAlbumId : state . album . id ) // 목적지 ID 주입
349271 return . none
350272
351273 case let . photoImport( . presented( . delegate( delegateAction) ) ) :
352274 switch delegateAction {
353- case . didImportPhotos :
275+ case let . didCompleteTask ( message ) :
354276 state. photoImport = nil
355- state. isLoading = true
356-
357- return . run { send in
358- // TODO: 선택한 사진들을 현재 앨범으로 복제하는 API 호출
359- try ? await Task . sleep ( for: . seconds( 1 ) ) // 임시 딜레이
360- await send ( . importPhotosResponse( . success( ( ) ) ) )
361- }
277+ return . merge(
278+ . send( . delegate( . showToast( NekiToastItem ( message, style: . success) ) ) ) ,
279+ . send( . fetchPhotos)
280+ )
362281
363282 case . didTapCancel:
364283 state. photoImport = nil
365284 return . none
285+
286+ case let . showToast( toastItem) :
287+ return . send( . delegate( . showToast( toastItem) ) )
366288 }
367289
368- case . importPhotosResponse( . success) :
369- state. isLoading = false
370- return . merge(
371- . send( . delegate( . showToast( NekiToastItem ( " 사진을 앨범에 가져왔어요 " , style: . success) ) ) ) ,
372- . send( . fetchPhotos)
373- )
374-
375- case . importPhotosResponse( . failure) :
376- state. isLoading = false
377- return . send( . delegate( . showToast( NekiToastItem ( " 사진을 가져오지 못했어요 " , style: . error) ) ) )
378-
379290 default : return . none
380291 }
381292 }
0 commit comments