diff --git a/SodaLive/Resources/Assets.xcassets/btn_follow_big.imageset/btn_follow_big.png b/SodaLive/Resources/Assets.xcassets/btn_follow_big.imageset/btn_follow_big.png index da6562c..f174603 100644 Binary files a/SodaLive/Resources/Assets.xcassets/btn_follow_big.imageset/btn_follow_big.png and b/SodaLive/Resources/Assets.xcassets/btn_follow_big.imageset/btn_follow_big.png differ diff --git a/SodaLive/Resources/Assets.xcassets/btn_following_big.imageset/btn_following_big.png b/SodaLive/Resources/Assets.xcassets/btn_following_big.imageset/btn_following_big.png index e2536c9..95935ee 100644 Binary files a/SodaLive/Resources/Assets.xcassets/btn_following_big.imageset/btn_following_big.png and b/SodaLive/Resources/Assets.xcassets/btn_following_big.imageset/btn_following_big.png differ diff --git a/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/Contents.json new file mode 100644 index 0000000..a392f31 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "btn_following_no_alarm_big.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/btn_following_no_alarm_big.png b/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/btn_following_no_alarm_big.png new file mode 100644 index 0000000..a2f4afa Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/btn_following_no_alarm_big.imageset/btn_following_no_alarm_big.png differ diff --git a/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/Contents.json new file mode 100644 index 0000000..aa387be --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_avatar_unfollow.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/ic_avatar_unfollow.png b/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/ic_avatar_unfollow.png new file mode 100644 index 0000000..fa09331 Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/ic_avatar_unfollow.imageset/ic_avatar_unfollow.png differ diff --git a/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/Contents.json new file mode 100644 index 0000000..731e65d --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_notify_all.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/ic_notify_all.png b/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/ic_notify_all.png new file mode 100644 index 0000000..2a129b1 Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/ic_notify_all.imageset/ic_notify_all.png differ diff --git a/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/Contents.json new file mode 100644 index 0000000..f516d09 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ic_notify_none.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/ic_notify_none.png b/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/ic_notify_none.png new file mode 100644 index 0000000..c88aa6c Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/ic_notify_none.imageset/ic_notify_none.png differ diff --git a/SodaLive/Sources/Dialog/CreatorFollowNotifyDialog.swift b/SodaLive/Sources/Dialog/CreatorFollowNotifyDialog.swift new file mode 100644 index 0000000..14736b5 --- /dev/null +++ b/SodaLive/Sources/Dialog/CreatorFollowNotifyDialog.swift @@ -0,0 +1,107 @@ +// +// CreatorFollowNotifyDialog.swift +// SodaLive +// +// Created by klaus on 9/23/24. +// + +import SwiftUI + +struct CreatorFollowNotifyDialog: View { + + @Binding var isShowing: Bool + let onClickNotifyAll: () -> Void + let onClickNotifyNone: () -> Void + let onClickUnFollow: () -> Void + + @State private var isShow: Bool = false + + var body: some View { + ZStack { + Color.black.opacity(0.7).ignoresSafeArea() + .onTapGesture { + isShowing = false + } + + VStack(spacing: 0) { + Spacer() + + if isShow { + VStack(alignment: .leading, spacing: 24) { + Text("알림") + .font(.custom(Font.bold.rawValue, size: 18.3)) + .foregroundColor(Color.grayee) + + CreatorFollowNotifyItem( + image: "ic_notify_all", + title: "전체", + onTapGesture: { + isShowing = false + onClickNotifyAll() + } + ) + CreatorFollowNotifyItem( + image: "ic_notify_none", + title: "없음", + onTapGesture: { + isShowing = false + onClickNotifyNone() + } + ) + CreatorFollowNotifyItem( + image: "ic_avatar_unfollow", + title: "팔로우 취소", + onTapGesture: { + isShowing = false + onClickUnFollow() + } + ) + } + .frame(maxWidth:.infinity) + .padding(.horizontal, 16) + .padding(.top, 16) + .padding(.bottom, 32) + .background(Color.gray22) + .cornerRadius(10, corners: [.topLeft, .topRight]) + .transition(.move(edge: .bottom)) + .animation(.easeInOut(duration: 0.5), value: isShow) + } + } + .ignoresSafeArea() + } + .onAppear { + withAnimation { + isShow = true + } + } + } +} + +struct CreatorFollowNotifyItem: View { + + let image: String + let title: String + let onTapGesture: () -> Void + + var body: some View { + HStack(spacing: 16) { + Image(image) + + Text(title) + .font(.custom(Font.medium.rawValue, size: 13.3)) + .foregroundColor(Color.grayee) + + Spacer() + } + .onTapGesture(perform: onTapGesture) + } +} + +#Preview { + CreatorFollowNotifyDialog( + isShowing: .constant(true), + onClickNotifyAll: {}, + onClickNotifyNone: {}, + onClickUnFollow: {} + ) +} diff --git a/SodaLive/Sources/Explorer/Profile/GetCreatorProfileResponse.swift b/SodaLive/Sources/Explorer/Profile/GetCreatorProfileResponse.swift index 632db8d..48f75f3 100644 --- a/SodaLive/Sources/Explorer/Profile/GetCreatorProfileResponse.swift +++ b/SodaLive/Sources/Explorer/Profile/GetCreatorProfileResponse.swift @@ -31,6 +31,8 @@ struct CreatorResponse: Decodable { let youtubeUrl: String? let websiteUrl: String? let blogUrl: String? + let isFollow: Bool + let isNotify: Bool let isNotification: Bool let notificationRecipientCount: Int } diff --git a/SodaLive/Sources/Explorer/Profile/UserProfileCreatorView.swift b/SodaLive/Sources/Explorer/Profile/UserProfileCreatorView.swift index d14793b..e366135 100644 --- a/SodaLive/Sources/Explorer/Profile/UserProfileCreatorView.swift +++ b/SodaLive/Sources/Explorer/Profile/UserProfileCreatorView.swift @@ -13,7 +13,7 @@ struct UserProfileCreatorView: View { let creator: CreatorResponse let creatorFollow: () -> Void - let creatorUnFollow: () -> Void + let showCreatorFollowNotifyDialog: () -> Void let shareChannel: () -> Void var body: some View { @@ -57,12 +57,16 @@ struct UserProfileCreatorView: View { } } else { VStack(alignment: .leading, spacing: 9.3) { - Image(creator.isNotification ? "btn_following_big" : "btn_follow_big") + Image( + creator.isFollow ? + creator.isNotify ? "btn_following_big": "btn_following_no_alarm_big" + : "btn_follow_big" + ) .resizable() .frame(width: 83.3, height: 26.7) .onTapGesture { - if creator.isNotification { - creatorUnFollow() + if creator.isFollow { + showCreatorFollowNotifyDialog() } else { creatorFollow() } @@ -143,11 +147,13 @@ struct UserProfileCreatorView_Previews: PreviewProvider { youtubeUrl: Optional("https://www.youtube.com/watch?v=3x2tfZnfLRo"), websiteUrl: Optional("https://instagram.com/dear.zia"), blogUrl: Optional("dear.zia"), + isFollow: false, + isNotify: false, isNotification: false, notificationRecipientCount: 2 ) ) { - } creatorUnFollow: { + } showCreatorFollowNotifyDialog: { } shareChannel: { } } diff --git a/SodaLive/Sources/Explorer/Profile/UserProfileView.swift b/SodaLive/Sources/Explorer/Profile/UserProfileView.swift index c1b303b..7258be9 100644 --- a/SodaLive/Sources/Explorer/Profile/UserProfileView.swift +++ b/SodaLive/Sources/Explorer/Profile/UserProfileView.swift @@ -14,6 +14,7 @@ struct UserProfileView: View { @State private var memberId: Int = 0 @State private var isShowMemberProfilePopup: Bool = false + @State private var isShowFollowNotifyDialog: Bool = false var body: some View { GeometryReader { proxy in @@ -52,8 +53,8 @@ struct UserProfileView: View { UserProfileCreatorView( creator: creatorProfile.creator) { viewModel.creatorFollow() - } creatorUnFollow: { - viewModel.creatorUnFollow() + } showCreatorFollowNotifyDialog: { + isShowFollowNotifyDialog = true } shareChannel: { viewModel.shareChannel(userId: userId) } @@ -323,6 +324,21 @@ struct UserProfileView: View { MemberProfileDialog(isShowing: $isShowMemberProfilePopup, memberId: memberId) } } + + if isShowFollowNotifyDialog { + CreatorFollowNotifyDialog( + isShowing: $isShowFollowNotifyDialog, + onClickNotifyAll: { + viewModel.creatorFollow(follow: true, notify: true) + }, + onClickNotifyNone: { + viewModel.creatorFollow(follow: true, notify: false) + }, + onClickUnFollow: { + viewModel.creatorFollow(follow: false, notify: false) + } + ) + } } .sheet( isPresented: $viewModel.isShowShareView, diff --git a/SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift b/SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift index 9415cbc..ccbf1dc 100644 --- a/SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift +++ b/SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift @@ -282,11 +282,11 @@ final class UserProfileViewModel: ObservableObject { .store(in: &subscription) } - func creatorFollow() { + func creatorFollow(follow: Bool = true, notify: Bool = true) { if let creator = creatorProfile { isLoading = true - userRepository.creatorFollow(creatorId: creator.creator.creatorId) + userRepository.creatorFollow(creatorId: creator.creator.creatorId, follow: follow, notify: notify) .sink { result in switch result { case .finished: diff --git a/SodaLive/Sources/User/CreatorFollowRequest.swift b/SodaLive/Sources/User/CreatorFollowRequest.swift index 47cf241..db64873 100644 --- a/SodaLive/Sources/User/CreatorFollowRequest.swift +++ b/SodaLive/Sources/User/CreatorFollowRequest.swift @@ -9,4 +9,6 @@ import Foundation struct CreatorFollowRequest: Encodable { let creatorId: Int + var isNotify: Bool = true + var isActive: Bool = true } diff --git a/SodaLive/Sources/User/UserRepository.swift b/SodaLive/Sources/User/UserRepository.swift index db00866..1ab68b0 100644 --- a/SodaLive/Sources/User/UserRepository.swift +++ b/SodaLive/Sources/User/UserRepository.swift @@ -69,8 +69,8 @@ final class UserRepository { return api.requestPublisher(.updatePushToken(request: PushTokenUpdateRequest(pushToken: pushToken))) } - func creatorFollow(creatorId: Int) -> AnyPublisher { - return api.requestPublisher(.creatorFollow(request: CreatorFollowRequest(creatorId: creatorId))) + func creatorFollow(creatorId: Int, follow: Bool = true, notify: Bool = true) -> AnyPublisher { + return api.requestPublisher(.creatorFollow(request: CreatorFollowRequest(creatorId: creatorId, isNotify: notify, isActive: follow))) } func creatorUnFollow(creatorId: Int) -> AnyPublisher {