diff --git a/Projects/Core/PPACData/Sources/DTO/MemeResponseDTO.swift b/Projects/Core/PPACData/Sources/DTO/MemeResponseDTO.swift index dc3cdb3..191f86d 100644 --- a/Projects/Core/PPACData/Sources/DTO/MemeResponseDTO.swift +++ b/Projects/Core/PPACData/Sources/DTO/MemeResponseDTO.swift @@ -55,7 +55,7 @@ struct MemeResponseDTO: Decodable { let updatedAt: String let isSaved: Bool let isReaction: Bool - let watch: Int + let watch: Int? public init( _id: String, diff --git a/Projects/Core/PPACData/Sources/Repository/MemeRepositoryImpl.swift b/Projects/Core/PPACData/Sources/Repository/MemeRepositoryImpl.swift index 6061337..4fe58ae 100644 --- a/Projects/Core/PPACData/Sources/Repository/MemeRepositoryImpl.swift +++ b/Projects/Core/PPACData/Sources/Repository/MemeRepositoryImpl.swift @@ -118,11 +118,8 @@ public class MemeRepositoryImpl: MemeRepository { let endpoint = MemeEndpoint.reaction(memeId: memeId, count: count) let result = await networkservice.request(endpoint, dataType: BaseDTO.self) switch result { - case .success(let data): - guard let data = data.data else { - throw NetworkError.dataDecodingError - } - return data.count + case .success(let count): + return count.data?.count ?? 0 case .failure(let failure): throw failure } diff --git a/Projects/Features/MemeDetail/Sources/MemeDetailView.swift b/Projects/Features/MemeDetail/Sources/MemeDetailView.swift index 1a69a52..a96e1c7 100644 --- a/Projects/Features/MemeDetail/Sources/MemeDetailView.swift +++ b/Projects/Features/MemeDetail/Sources/MemeDetailView.swift @@ -40,15 +40,17 @@ public struct MemeDetailView: View { tabBarTap(tab) } .background( - KFImage(URL(string: viewModel.state.meme.imageUrlString)) - .resizable() - .loadDiskFileSynchronously() - .cacheMemoryOnly() - .aspectRatio(contentMode: .fill) - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) - .clipped() - .opacity(0.4) - .edgesIgnoringSafeArea(.top) + KFImage(URL(string: viewModel.state.meme.imageUrlString)) + .resizable() + .loadDiskFileSynchronously() + .cacheMemoryOnly() + .aspectRatio(contentMode: .fill) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .clipped() + .opacity(0.4) // Image Opacity: 40% + .blur(radius: 50) // Layer Blur: 50 + .overlay(Color.white.opacity(0.3)) // White Dim: #fff, Opacity: 30% + .edgesIgnoringSafeArea(.top) ) .onAppear { viewModel.logMemeDetail(interaction: .view, event: .meme) diff --git a/Projects/Features/MemeDetail/Sources/MemeDetailViewModel.swift b/Projects/Features/MemeDetail/Sources/MemeDetailViewModel.swift index a330427..8397504 100644 --- a/Projects/Features/MemeDetail/Sources/MemeDetailViewModel.swift +++ b/Projects/Features/MemeDetail/Sources/MemeDetailViewModel.swift @@ -47,6 +47,9 @@ public final class MemeDetailViewModel: ViewModelType, ObservableObject { private let watchMemeUseCase: WatchMemeUseCase private let reactToMemeUseCase: ReactToMemeUseCase + private var reactionCount = 0 + private var reactionTask: Task? + // MARK: - Initializers public init( @@ -67,7 +70,8 @@ public final class MemeDetailViewModel: ViewModelType, ObservableObject { } deinit { - print("memeviewmodel deinit") + print("memeviewmodel deinit") + reactionTask?.cancel() } // MARK: - Methods @@ -110,23 +114,50 @@ public final class MemeDetailViewModel: ViewModelType, ObservableObject { } private extension MemeDetailViewModel { - + @MainActor - func postReaction() async { - do { - let memeReactionCount = try await reactToMemeUseCase.execute( - memeId: state.meme.id, - count: 1 - ) - - self.state.meme.reaction = memeReactionCount + func postReaction() { + reactionCount += 1 + self.state.meme.reaction += 1 self.state.meme.isReaction = true self.logMemeDetail(event: .reaction) - print("reaction success") - } catch { - // TODO: - 에러처리 - print("Failed to post reaction: \(error)") - } + + reactionTask?.cancel() + + reactionTask = Task { [weak self] in + guard let self = self else { return } + do { + try await Task.sleep(nanoseconds: 3 * 1_000_000_000) + await self.sendReactions() + } catch { + if Task.isCancelled { + // 태스크가 취소되었으므로 아무 작업도 하지 않음 + return + } else { + print("Task error: \(error)") + } + } + } + } + + + @MainActor + func sendReactions() async { + let count = reactionCount + guard count > 0 else { + // 전송할 리액션이 없음 + return + } + reactionCount = 0 + do { + let count = try await reactToMemeUseCase.execute(memeId: state.meme.id, count: count) + print("currentMeme count: \(self.state.meme.reaction)") + print("new count: \(count)") + self.state.meme.reaction = count + print("Reactions sent successfully with count: \(count)") + } catch { + print("Failed to send reactions: \(error)") + } } @MainActor