162 lines
5.6 KiB
Swift
162 lines
5.6 KiB
Swift
import SwiftUI
|
|
|
|
struct CreatorChannelFanTalkTabView: View {
|
|
let creatorId: Int
|
|
let isOwnCreatorChannel: Bool
|
|
@ObservedObject var viewModel: CreatorChannelFanTalkViewModel
|
|
let onTapWrite: () -> Void
|
|
let onTapEdit: (CreatorChannelFanTalkItemResponse) -> Void
|
|
|
|
@State private var actionPopupFanTalk: CreatorChannelFanTalkItemResponse?
|
|
@State private var fanTalkItemFrames = [Int: CGRect]()
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .topTrailing) {
|
|
content
|
|
|
|
actionPopupLayer
|
|
.zIndex(1)
|
|
}
|
|
.coordinateSpace(name: Self.coordinateSpaceName)
|
|
.background(Color.black)
|
|
.onPreferenceChange(CreatorChannelFanTalkItemFramePreferenceKey.self) { frames in
|
|
fanTalkItemFrames.merge(frames) { _, new in new }
|
|
}
|
|
.onAppear {
|
|
if viewModel.hasLoaded == false {
|
|
viewModel.fetchFirstPage(creatorId: creatorId)
|
|
}
|
|
}
|
|
.sodaToast(isPresented: $viewModel.isShowPopup, message: viewModel.errorMessage, autohideIn: 1)
|
|
.overlay(reportDialog)
|
|
.overlay(deleteDialog)
|
|
}
|
|
|
|
private var content: some View {
|
|
VStack(spacing: 0) {
|
|
CreatorChannelFanTalkCountBar(fanTalkCount: viewModel.fanTalkCount)
|
|
|
|
if isEmptyState {
|
|
CreatorChannelFanTalkEmptyView(
|
|
showsWriteButton: isOwnCreatorChannel == false,
|
|
onTapWrite: onTapWrite
|
|
)
|
|
} else {
|
|
LazyVStack(spacing: 0) {
|
|
ForEach(viewModel.fanTalks) { fanTalk in
|
|
fanTalkItem(fanTalk)
|
|
.onAppear {
|
|
viewModel.fetchNextPageIfNeeded(
|
|
creatorId: creatorId,
|
|
currentItem: fanTalk
|
|
)
|
|
}
|
|
}
|
|
|
|
if viewModel.isLoadingNextPage {
|
|
ProgressView()
|
|
.padding(.vertical, SodaSpacing.s20)
|
|
}
|
|
}
|
|
.padding(.bottom, SodaSpacing.s20)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func fanTalkItem(_ fanTalk: CreatorChannelFanTalkItemResponse) -> some View {
|
|
let isMine = fanTalk.writerId == UserDefaults.int(forKey: .userId)
|
|
|
|
return CreatorChannelFanTalkListItem(
|
|
fanTalk: fanTalk,
|
|
isMine: isMine,
|
|
isOwnCreatorChannel: isOwnCreatorChannel,
|
|
onTapReport: {
|
|
actionPopupFanTalk = nil
|
|
viewModel.presentReportDialog(fanTalkId: fanTalk.fanTalkId)
|
|
},
|
|
onTapMore: {
|
|
actionPopupFanTalk = actionPopupFanTalk?.fanTalkId == fanTalk.fanTalkId ? nil : fanTalk
|
|
}
|
|
)
|
|
.background {
|
|
GeometryReader { proxy in
|
|
Color.clear.preference(
|
|
key: CreatorChannelFanTalkItemFramePreferenceKey.self,
|
|
value: [fanTalk.fanTalkId: proxy.frame(in: .named(Self.coordinateSpaceName))]
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var actionPopupLayer: some View {
|
|
if let fanTalk = actionPopupFanTalk,
|
|
let itemFrame = fanTalkItemFrames[fanTalk.fanTalkId] {
|
|
let isMine = fanTalk.writerId == UserDefaults.int(forKey: .userId)
|
|
|
|
CreatorChannelFanTalkActionPopup(
|
|
isMine: isMine,
|
|
isOwnCreatorChannel: isOwnCreatorChannel,
|
|
onTapEdit: {
|
|
actionPopupFanTalk = nil
|
|
onTapEdit(fanTalk)
|
|
},
|
|
onTapDelete: {
|
|
actionPopupFanTalk = nil
|
|
viewModel.presentDeleteDialog(fanTalkId: fanTalk.fanTalkId)
|
|
}
|
|
)
|
|
.padding(.top, itemFrame.minY + 44)
|
|
.padding(.trailing, SodaSpacing.s14)
|
|
}
|
|
}
|
|
|
|
private var isEmptyState: Bool {
|
|
guard viewModel.hasLoaded else { return false }
|
|
return viewModel.fanTalkCount == 0
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var reportDialog: some View {
|
|
if viewModel.isShowReportDialog {
|
|
CheersReportDialogView(
|
|
isShowing: $viewModel.isShowReportDialog,
|
|
confirmAction: { reason in
|
|
viewModel.report(reason: reason)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var deleteDialog: some View {
|
|
if viewModel.isShowDeleteDialog {
|
|
SodaDialog(
|
|
title: I18n.MemberChannel.cheersDeleteTitle,
|
|
desc: I18n.Common.confirmDeleteQuestion,
|
|
confirmButtonTitle: I18n.Common.delete,
|
|
confirmButtonAction: {
|
|
viewModel.isShowDeleteDialog = false
|
|
viewModel.deleteSelectedFanTalk(creatorId: creatorId)
|
|
},
|
|
cancelButtonTitle: I18n.Common.cancel,
|
|
cancelButtonAction: {
|
|
viewModel.isShowDeleteDialog = false
|
|
viewModel.selectedFanTalkId = 0
|
|
},
|
|
textAlignment: .center
|
|
)
|
|
}
|
|
}
|
|
|
|
private static let coordinateSpaceName = "CreatorChannelFanTalkTabView"
|
|
}
|
|
|
|
private struct CreatorChannelFanTalkItemFramePreferenceKey: PreferenceKey {
|
|
static var defaultValue: [Int: CGRect] = [:]
|
|
|
|
static func reduce(value: inout [Int: CGRect], nextValue: () -> [Int: CGRect]) {
|
|
value.merge(nextValue()) { _, new in new }
|
|
}
|
|
}
|