diff --git a/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/Contents.json new file mode 100644 index 00000000..6e2e6aec --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "ic_new_following_white.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/ic_new_following_white.png b/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/ic_new_following_white.png new file mode 100644 index 00000000..18cd5e13 Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/v2/ic_new_following_white.imageset/ic_new_following_white.png differ diff --git a/SodaLive/Sources/Follow/FollowCreatorItemView.swift b/SodaLive/Sources/Follow/FollowCreatorItemView.swift index d1baffea..28028b83 100644 --- a/SodaLive/Sources/Follow/FollowCreatorItemView.swift +++ b/SodaLive/Sources/Follow/FollowCreatorItemView.swift @@ -13,6 +13,19 @@ struct FollowCreatorItemView: View { let creator: GetCreatorFollowingAllListItem let onClickFollow: (Int) -> Void let showCreatorFollowNotifyDialog: (Int) -> Void + let onTapUnfollow: ((Int) -> Void)? + + init( + creator: GetCreatorFollowingAllListItem, + onClickFollow: @escaping (Int) -> Void, + showCreatorFollowNotifyDialog: @escaping (Int) -> Void, + onTapUnfollow: ((Int) -> Void)? = nil + ) { + self.creator = creator + self.onClickFollow = onClickFollow + self.showCreatorFollowNotifyDialog = showCreatorFollowNotifyDialog + self.onTapUnfollow = onTapUnfollow + } var body: some View { VStack(spacing: 13.3) { @@ -36,19 +49,7 @@ struct FollowCreatorItemView: View { Spacer() - let asset = FollowButtonImageAsset( - type: creator.isFollow - ? (creator.isNotify ? .following : .followingNoAlarm) - : .follow - ) - asset.imageView() - .onTapGesture { - if creator.isFollow { - showCreatorFollowNotifyDialog(creator.creatorId) - } else { - onClickFollow(creator.creatorId) - } - } + followButton } Rectangle() @@ -56,4 +57,33 @@ struct FollowCreatorItemView: View { .frame(height: 0.5) } } + + @ViewBuilder + private var followButton: some View { + if creator.isFollow, let onTapUnfollow { + Button(action: { onTapUnfollow(creator.creatorId) }) { + Image("ic_new_following_white") + .resizable() + .frame(width: 20, height: 20) + .frame(width: 36, height: 36) + .background(Color.gray800) + .clipShape(Circle()) + } + .buttonStyle(.plain) + } else { + let asset = FollowButtonImageAsset( + type: creator.isFollow + ? (creator.isNotify ? .following : .followingNoAlarm) + : .follow + ) + asset.imageView() + .onTapGesture { + if creator.isFollow { + showCreatorFollowNotifyDialog(creator.creatorId) + } else { + onClickFollow(creator.creatorId) + } + } + } + } } diff --git a/SodaLive/Sources/Follow/FollowCreatorView.swift b/SodaLive/Sources/Follow/FollowCreatorView.swift index fed50fe5..b3d1eafe 100644 --- a/SodaLive/Sources/Follow/FollowCreatorView.swift +++ b/SodaLive/Sources/Follow/FollowCreatorView.swift @@ -11,9 +11,10 @@ struct FollowCreatorView: View { @StateObject var viewModel = FollowCreatorViewModel() - @State private var isShowFollowNotifyDialog: Bool = false + @State private var isShowUnfollowConfirmDialog: Bool = false @State private var creatorId: Int = 0 @State private var selectedItemIndex: Int = 0 + @State private var creatorName: String = "" var body: some View { BaseView(isLoading: $viewModel.isLoading) { @@ -48,7 +49,12 @@ struct FollowCreatorView: View { showCreatorFollowNotifyDialog: { creatorId = $0 selectedItemIndex = index - isShowFollowNotifyDialog = true + }, + onTapUnfollow: { + creatorId = $0 + creatorName = creator.nickname + selectedItemIndex = index + isShowUnfollowConfirmDialog = true } ) .padding(.horizontal, 20) @@ -77,41 +83,44 @@ struct FollowCreatorView: View { } .sodaToast(isPresented: $viewModel.isShowPopup, message: viewModel.errorMessage, autohideIn: 2) - if isShowFollowNotifyDialog { - CreatorFollowNotifyDialog( - isShowing: $isShowFollowNotifyDialog, - onClickNotifyAll: { - viewModel.creatorFollow( - creatorId: creatorId, - index: selectedItemIndex, - follow: true, - notify: true - ) - creatorId = 0 - selectedItemIndex = -1 - }, - onClickNotifyNone: { - viewModel.creatorFollow( - creatorId: creatorId, - index: selectedItemIndex, - follow: true, - notify: false - ) - creatorId = 0 - selectedItemIndex = -1 - }, - onClickUnFollow: { - viewModel.creatorFollow( - creatorId: creatorId, - index: selectedItemIndex, - follow: false, - notify: false - ) - creatorId = 0 - selectedItemIndex = -1 - } - ) + if isShowUnfollowConfirmDialog { + unfollowConfirmDialog } } } + + private var unfollowConfirmDialog: some View { + SodaV2ActionModal( + title: I18n.MemberChannel.unfollowActionModalTitle, + message: I18n.MemberChannel.unfollowActionModalMessage(creatorName), + button1: SodaV2ActionModalButton( + label: I18n.MemberChannel.unfollowActionModalConfirm, + action: confirmUnfollow + ), + button2: SodaV2ActionModalButton( + label: I18n.MemberChannel.unfollowActionModalCancel, + action: dismissUnfollowConfirmDialog + ), + onDimmedTap: dismissUnfollowConfirmDialog + ) + } + + private func confirmUnfollow() { + let targetCreatorId = creatorId + let targetIndex = selectedItemIndex + dismissUnfollowConfirmDialog() + viewModel.creatorFollow( + creatorId: targetCreatorId, + index: targetIndex, + follow: false, + notify: false + ) + } + + private func dismissUnfollowConfirmDialog() { + isShowUnfollowConfirmDialog = false + creatorId = 0 + selectedItemIndex = -1 + creatorName = "" + } } diff --git a/SodaLive/Sources/I18n/I18n.swift b/SodaLive/Sources/I18n/I18n.swift index edda681d..8fff8b5b 100644 --- a/SodaLive/Sources/I18n/I18n.swift +++ b/SodaLive/Sources/I18n/I18n.swift @@ -2740,6 +2740,16 @@ enum I18n { ja: "\(nickname)さんのフォローを解除しますか?" ) } + static var unfollowActionModalTitle: String { pick(ko: "팔로우 해제", en: "Unfollow", ja: "フォロー解除") } + static func unfollowActionModalMessage(_ nickname: String) -> String { + pick( + ko: "팔로우를 해제할까요?\n\(nickname)의 소식을 받을 수 없어요.", + en: "You won't receive updates from \(nickname).\nUnfollow this creator?", + ja: "\(nickname)からの最新情報を受け取れなくなります。\nフォローを解除しますか?" + ) + } + static var unfollowActionModalCancel: String { pick(ko: "취소", en: "Cancel", ja: "キャンセル") } + static var unfollowActionModalConfirm: String { pick(ko: "해제하기", en: "Unfollow", ja: "解除する") } static var liveOnNow: String { pick(ko: "현재 라이브 중입니다.", en: "Live is currently ongoing.", ja: "現在ライブ配信中です。") } static var cannotReserveOwnLive: String { pick(ko: "내가 만든 라이브는 예약할 수 없습니다.", en: "reserve a live you created is required.", ja: "自分が作ったライブは予約できません。") } diff --git a/SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift b/SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift index 4f80c7a4..fc0d2d5e 100644 --- a/SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift +++ b/SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift @@ -23,6 +23,7 @@ struct CreatorChannelView: View { @State private var isShowUserBlockConfirm = false @State private var isShowUserReport = false @State private var isShowProfileReport = false + @State private var isShowUnfollowConfirmDialog = false @State private var isCreatorActionMenuPresented = false @State private var pendingAction: (() -> Void)? = nil @State private var payload = Payload() @@ -164,6 +165,10 @@ struct CreatorChannelView: View { fanTalkDeleteDialog } + if isShowUnfollowConfirmDialog { + unfollowConfirmDialog + } + if isShowChannelDonationDialog { LiveRoomDonationDialogView( isShowing: $isShowChannelDonationDialog, @@ -273,7 +278,7 @@ struct CreatorChannelView: View { viewModel.creatorFollow(follow: true, notify: true) }, onTapUnfollow: { - viewModel.creatorFollow(follow: false, notify: false) + isShowUnfollowConfirmDialog = true }, onTapNotify: { viewModel.creatorFollow(follow: true, notify: true) @@ -443,6 +448,31 @@ struct CreatorChannelView: View { fanTalkViewModel.selectedFanTalkId = 0 } + private var unfollowConfirmDialog: some View { + SodaV2ActionModal( + title: I18n.MemberChannel.unfollowActionModalTitle, + message: I18n.MemberChannel.unfollowActionModalMessage(viewModel.response?.creator.nickname ?? ""), + button1: SodaV2ActionModalButton( + label: I18n.MemberChannel.unfollowActionModalConfirm, + action: confirmUnfollow + ), + button2: SodaV2ActionModalButton( + label: I18n.MemberChannel.unfollowActionModalCancel, + action: dismissUnfollowConfirmDialog + ), + onDimmedTap: dismissUnfollowConfirmDialog + ) + } + + private func confirmUnfollow() { + isShowUnfollowConfirmDialog = false + viewModel.creatorFollow(follow: false, notify: false) + } + + private func dismissUnfollowConfirmDialog() { + isShowUnfollowConfirmDialog = false + } + private var authView: some View { BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION) .onConfirm { _ in true }