라이브 방 추가
This commit is contained in:
72
SodaLive/Sources/Live/Room/Dialog/LiveRoomDialogView.swift
Normal file
72
SodaLive/Sources/Live/Room/Dialog/LiveRoomDialogView.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// LiveRoomDialogView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/14.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LiveRoomDialogView: View {
|
||||
|
||||
let content: String
|
||||
|
||||
let cancelTitle: String?
|
||||
let cancelAction: (() -> Void)?
|
||||
|
||||
let confirmTitle: String?
|
||||
let confirmAction: (() -> Void)?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(alignment: .center, spacing: 11.7) {
|
||||
Image("ic_request_speak")
|
||||
.resizable()
|
||||
.frame(width: 36, height: 36)
|
||||
|
||||
Text(content)
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
.padding(.horizontal, 26.7)
|
||||
|
||||
HStack(spacing: 10) {
|
||||
Spacer()
|
||||
|
||||
if let cancelTitle = cancelTitle, let cancelAction = cancelAction {
|
||||
Text(cancelTitle)
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(.white)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 8.3)
|
||||
.background(Color.white.opacity(0.2))
|
||||
.cornerRadius(13.3)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 13.3)
|
||||
.strokeBorder()
|
||||
.foregroundColor(.white)
|
||||
)
|
||||
.onTapGesture { cancelAction() }
|
||||
}
|
||||
|
||||
if let confirmTitle = confirmTitle, let confirmAction = confirmAction {
|
||||
Text(confirmTitle)
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 8.3)
|
||||
.background(Color.white)
|
||||
.cornerRadius(13.3)
|
||||
.onTapGesture { confirmAction() }
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 26.7)
|
||||
.padding(.top, confirmTitle != nil || cancelTitle != nil ? 10 : 0)
|
||||
}
|
||||
.padding(.vertical, 20)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(16.7)
|
||||
.padding(.horizontal, 26.7)
|
||||
.frame(width: screenSize().width)
|
||||
}
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// LiveRoomDonationMessageDialog.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LiveRoomDonationMessageDialog: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
@StateObject var viewModel = LiveRoomViewModel()
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color.black
|
||||
.opacity(0.7)
|
||||
.ignoresSafeArea()
|
||||
.onTapGesture {
|
||||
hideKeyboard()
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("후원메시지")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("(\(viewModel.donationMessageCount))")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("닫기")
|
||||
.font(.custom(Font.light.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.onTapGesture { isShowing = false }
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
if viewModel.donationMessageList.count > 0 {
|
||||
LazyVStack(spacing: 10.7) {
|
||||
ForEach(0..<viewModel.donationMessageList.count, id: \.self) { index in
|
||||
let donationMessage = viewModel.donationMessageList[index]
|
||||
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("\(donationMessage.nickname)님이")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text("\(donationMessage.canMessage)")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(.white)
|
||||
|
||||
Text("'\(donationMessage.donationMessage)'")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_close_white")
|
||||
.resizable()
|
||||
.frame(width: 13.3, height: 13.3)
|
||||
.onTapGesture {
|
||||
viewModel.deleteDonationMessage(uuid: donationMessage.uuid)
|
||||
}
|
||||
}
|
||||
.padding(13.3)
|
||||
.background(Color(hex: "333333"))
|
||||
.cornerRadius(5.3)
|
||||
.onTapGesture {
|
||||
UIPasteboard.general.string = donationMessage.donationMessage
|
||||
self.viewModel.errorMessage = "후원 메시지가 복사되었습니다."
|
||||
self.viewModel.isShowPopup = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, 18.7)
|
||||
} else {
|
||||
Text("후원메시지가 없습니다.")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.padding(.top, 30)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(20)
|
||||
.background(Color(hex: "222222"))
|
||||
.cornerRadius(8)
|
||||
|
||||
if viewModel.isLoading {
|
||||
LoadingView()
|
||||
}
|
||||
}
|
||||
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .bottom, autohideIn: 2) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text(viewModel.errorMessage)
|
||||
.padding(.vertical, 13.3)
|
||||
.frame(width: screenSize().width - 66.7, alignment: .center)
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.background(Color(hex: "9970ff"))
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.leading)
|
||||
.cornerRadius(20)
|
||||
.padding(.bottom, 66.7)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.getDonationMessageList()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// LiveRoomDonationRankingDialog.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LiveRoomDonationRankingDialog: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
@StateObject var viewModel = LiveRoomViewModel()
|
||||
|
||||
let columns = [GridItem(.flexible())]
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("현재 라이브 후원랭킹")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_close_white")
|
||||
.onTapGesture { isShowing = false }
|
||||
}
|
||||
|
||||
if let donationStatus = viewModel.donationStatus {
|
||||
LiveRoomDonationRankingTotalCanView(totalCan: donationStatus.totalCan)
|
||||
.padding(.top, 25)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("전체")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("\(donationStatus.totalCount)")
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.leading, 6.7)
|
||||
|
||||
Text("명")
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 13.3)
|
||||
|
||||
ScrollView(showsIndicators: false) {
|
||||
LazyVGrid(columns: columns, spacing: 0) {
|
||||
ForEach(0..<donationStatus.donationList.count, id: \.self) { index in
|
||||
let item = donationStatus.donationList[index]
|
||||
LiveRoomDonationRankingItemView(
|
||||
index: index,
|
||||
item: item,
|
||||
itemCount: donationStatus.donationList.count
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, 8)
|
||||
}
|
||||
}
|
||||
.padding(20)
|
||||
.background(Color(hex: "222222"))
|
||||
.cornerRadius(8)
|
||||
|
||||
if viewModel.isLoading {
|
||||
LoadingView()
|
||||
}
|
||||
}
|
||||
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .bottom, autohideIn: 2) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text(viewModel.errorMessage)
|
||||
.padding(.vertical, 13.3)
|
||||
.frame(width: screenSize().width - 66.7, alignment: .center)
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.background(Color(hex: "9970ff"))
|
||||
.foregroundColor(Color.white)
|
||||
.multilineTextAlignment(.leading)
|
||||
.cornerRadius(20)
|
||||
.padding(.bottom, 66.7)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.getDonationStatus()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// LiveRoomDonationRankingItemView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomDonationRankingItemView: View {
|
||||
|
||||
let index: Int
|
||||
let item: GetLiveRoomDonationItem
|
||||
let itemCount: Int
|
||||
|
||||
let rankingCrawns = ["ic_crown_1", "ic_crown_2", "ic_crown_3"]
|
||||
let rankingColors = [
|
||||
[Color(hex: "ffdc00"), Color(hex: "ffb600")],
|
||||
[Color(hex: "ffffff"), Color(hex: "9f9f9f")],
|
||||
[Color(hex: "e6a77a"), Color(hex: "c67e4a")],
|
||||
[Color(hex: "ffffff").opacity(0), Color(hex: "ffffff").opacity(0)]
|
||||
]
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
ZStack {
|
||||
KFImage(URL(string: item.profileImage))
|
||||
.cancelOnDisappear(true)
|
||||
.downsampling(size: CGSize(width: 60, height: 60))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(width: 60, height: 60, alignment: .top)
|
||||
.clipShape(Circle())
|
||||
.overlay(
|
||||
Circle()
|
||||
.stroke(
|
||||
AngularGradient(colors: rankingColors[index < 4 ? index : 3], center: .center),
|
||||
lineWidth: 3
|
||||
)
|
||||
)
|
||||
|
||||
if index < 3 {
|
||||
VStack(alignment: .trailing, spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
Image(rankingCrawns[index])
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25)
|
||||
}
|
||||
.frame(width: 63, height: 63, alignment: .trailing)
|
||||
}
|
||||
}
|
||||
.frame(width: 63, height: 63)
|
||||
|
||||
Text("\(index + 1)")
|
||||
.font(.custom(Font.bold.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.padding(.leading, 20)
|
||||
.padding(.trailing, 13.3)
|
||||
|
||||
let nickname = item.nickname.count > 10 ? "\(String(item.nickname.prefix(10)))..." : item.nickname
|
||||
Text(nickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
if item.can > 0 {
|
||||
Text("\(item.can) 코인")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, isTop3Index(index: index) ? 20 : 0)
|
||||
.padding(.top, getTopPadding(index: index))
|
||||
.padding(.bottom, getBottomPadding(index: index))
|
||||
.background(Color(hex: "2b2635").opacity(isTop3Index(index: index) ? 1 : 0))
|
||||
.cornerRadius(4.7, corners: cornerRadiusConers(index: index))
|
||||
.padding(.horizontal, isTop3Index(index: index) ? 0 : 6.7)
|
||||
}
|
||||
|
||||
private func isTop3Index(index: Int) -> Bool {
|
||||
return index == 0 || index == 1 || index == 2
|
||||
}
|
||||
|
||||
private func getTopPadding(index: Int) -> CGFloat {
|
||||
if index == 0 || index == 3 {
|
||||
return 20
|
||||
} else {
|
||||
return 6.7
|
||||
}
|
||||
}
|
||||
|
||||
private func getBottomPadding(index: Int) -> CGFloat {
|
||||
if (index == 0 && itemCount == 1) || (index == 1 && itemCount == 2) || index == 2 {
|
||||
return 20
|
||||
} else {
|
||||
return 6.7
|
||||
}
|
||||
}
|
||||
|
||||
private func cornerRadiusConers(index: Int) -> UIRectCorner {
|
||||
if (index == 0 && itemCount == 1) {
|
||||
return [.topLeft, .topRight, .bottomLeft, .bottomRight]
|
||||
} else if index == 0 {
|
||||
return [.topLeft, .topRight]
|
||||
} else if (index == 1 && itemCount == 2) || index == 2 {
|
||||
return [.bottomLeft, .bottomRight]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// LiveRoomDonationRankingTotalCanView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LiveRoomDonationRankingTotalCanView: View {
|
||||
|
||||
let totalCan: Int
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 0) {
|
||||
Text("합계")
|
||||
.font(.custom(Font.bold.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "d2d2d2"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("\(totalCan)")
|
||||
.font(.custom(Font.medium.rawValue, size: 16))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
|
||||
Text("캔")
|
||||
.font(.custom(Font.medium.rawValue, size: 10.7))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
.padding(.horizontal, 18.7)
|
||||
.padding(.vertical, 10.7)
|
||||
.background(Color(hex: "2b2635"))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
238
SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift
Normal file
238
SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift
Normal file
@@ -0,0 +1,238 @@
|
||||
//
|
||||
// LiveRoomInfoEditDialog.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomInfoEditDialog: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
@Binding var isShowPhotoPicker: Bool
|
||||
|
||||
@State private var title = ""
|
||||
@State private var notice = ""
|
||||
|
||||
let placeholder = "라이브 공지를 입력하세요"
|
||||
|
||||
let viewModel: LiveRoomViewModel
|
||||
|
||||
let isLoading: Bool
|
||||
let coverImageUrl: String?
|
||||
let coverImage: UIImage?
|
||||
var confirmAction: (String, String) -> Void
|
||||
|
||||
init(
|
||||
isShowing: Binding<Bool>,
|
||||
isShowPhotoPicker: Binding<Bool>,
|
||||
viewModel: LiveRoomViewModel,
|
||||
isLoading: Bool,
|
||||
currentTitle: String,
|
||||
currentNotice: String,
|
||||
coverImageUrl: String,
|
||||
coverImage: UIImage?,
|
||||
confirmAction: @escaping (String, String) -> Void
|
||||
) {
|
||||
self._isShowing = isShowing
|
||||
self._isShowPhotoPicker = isShowPhotoPicker
|
||||
|
||||
self.viewModel = viewModel
|
||||
self.isLoading = isLoading
|
||||
|
||||
self.title = currentTitle
|
||||
self.notice = currentNotice
|
||||
self.coverImageUrl = coverImageUrl
|
||||
self.coverImage = coverImage
|
||||
self.confirmAction = confirmAction
|
||||
|
||||
UITextView.appearance().backgroundColor = .clear
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
GeometryReader { proxy in
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("라이브 수정")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_close_white")
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
ZStack {
|
||||
if let coverImage = coverImage {
|
||||
Image(uiImage: coverImage)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(width: 80, height: 116.8, alignment: .top)
|
||||
.clipped()
|
||||
.cornerRadius(10)
|
||||
} else if let coverImageUrl = coverImageUrl {
|
||||
KFImage(URL(string: coverImageUrl))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(width: 80, height: 116.8, alignment: .top)
|
||||
.clipped()
|
||||
.cornerRadius(10)
|
||||
} else {
|
||||
Image("ic_logo_220")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 80, height: 116.8)
|
||||
.background(Color(hex: "3e3358"))
|
||||
.cornerRadius(10)
|
||||
}
|
||||
|
||||
Image("ic_camera")
|
||||
.padding(10)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(30)
|
||||
.offset(x: 40, y: 40)
|
||||
}
|
||||
.frame(alignment: .bottomTrailing)
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
isShowPhotoPicker = true
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
TitleInputView()
|
||||
.padding(.top, 40)
|
||||
|
||||
ContentInputView()
|
||||
.padding(.top, 33.3)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Text("취소")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.vertical, 16)
|
||||
.frame(width: (screenSize().width - 40) / 2)
|
||||
.background(Color(hex: "9970ff").opacity(0.2))
|
||||
.cornerRadius(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
Text("수정하기")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(.white)
|
||||
.padding(.vertical, 16)
|
||||
.frame(width: (screenSize().width - 40) / 2)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(10)
|
||||
.onTapGesture {
|
||||
confirmAction(
|
||||
title,
|
||||
notice.trimmingCharacters(in: .whitespacesAndNewlines) != placeholder ? notice : ""
|
||||
)
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
.padding(.top, 45)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(13.3)
|
||||
.frame(width: proxy.size.width, height: proxy.size.height)
|
||||
.onTapGesture { hideKeyboard() }
|
||||
}
|
||||
.background(Color(hex: "222222").edgesIgnoringSafeArea(.all))
|
||||
}
|
||||
|
||||
if viewModel.isShowPopup {
|
||||
LiveRoomDialogView(
|
||||
content: viewModel.errorMessage,
|
||||
cancelTitle: viewModel.popupCancelTitle,
|
||||
cancelAction: viewModel.popupCancelAction,
|
||||
confirmTitle: viewModel.popupConfirmTitle,
|
||||
confirmAction: viewModel.popupConfirmAction
|
||||
).onAppear {
|
||||
if viewModel.popupConfirmTitle == nil && viewModel.popupConfirmAction == nil {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
viewModel.isShowPopup = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isLoading {
|
||||
LoadingView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func TitleInputView() -> some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text("제목")
|
||||
.font(.custom(Font.bold.rawValue, size: 16.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
TextField("라이브 제목을 입력하세요", text: $title)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.accentColor(Color(hex: "9970ff"))
|
||||
.keyboardType(.default)
|
||||
.padding(.top, 12)
|
||||
.padding(.horizontal, 6.7)
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(Color(hex: "909090").opacity(0.7))
|
||||
.padding(.top, 8.3)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func ContentInputView() -> some View {
|
||||
VStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
Text("공지")
|
||||
.font(.custom(Font.bold.rawValue, size: 16.7))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("\(notice.count)자")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "ff5c49")) +
|
||||
Text(" / 1000자")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
}
|
||||
|
||||
TextViewWrapper(
|
||||
text: $notice,
|
||||
placeholder: placeholder,
|
||||
textColorHex: "eeeeee",
|
||||
backgroundColorHex: "303030"
|
||||
)
|
||||
.frame(width: screenSize().width - 26.7, height: 133.3)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 13.3)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// LiveRoomProfileDialog.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomProfileDialog: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
let profileInfo: LiveRoomMember
|
||||
let creatorId: Int
|
||||
let isSpeaker: Bool
|
||||
|
||||
let memberId = UserDefaults.int(forKey: .userId)
|
||||
|
||||
var onClickInviteSpeaker: ((Int) -> Void)? = nil
|
||||
var onClickChangeListener: ((Int) -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color.black.opacity(0.7).ignoresSafeArea()
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
KFImage(URL(string: profileInfo.profileImage))
|
||||
.resizable()
|
||||
.frame(width: 80, height: 116.7, alignment: .top)
|
||||
.clipped()
|
||||
.cornerRadius(13.3)
|
||||
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text(profileInfo.nickname)
|
||||
.font(.custom(Font.bold.rawValue, size: 20))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.padding(.top, 6.7)
|
||||
|
||||
Spacer()
|
||||
|
||||
if isSpeaker {
|
||||
if profileInfo.role == .LISTENER, let onClickInviteSpeaker = onClickInviteSpeaker {
|
||||
Text("스피커로 초대")
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.horizontal, 15.4)
|
||||
.padding(.vertical, 8.3)
|
||||
.background(Color.white)
|
||||
.cornerRadius(13.3)
|
||||
.onTapGesture {
|
||||
onClickInviteSpeaker(profileInfo.id)
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
if (memberId == creatorId || memberId == profileInfo.id) && profileInfo.id != creatorId && profileInfo.role == .SPEAKER,
|
||||
let onClickChangeListener = onClickChangeListener {
|
||||
Text("리스너로 변경")
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.horizontal, 15.4)
|
||||
.padding(.vertical, 8.3)
|
||||
.background(Color.white)
|
||||
.cornerRadius(13.3)
|
||||
.onTapGesture {
|
||||
onClickChangeListener(profileInfo.id)
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 116.7)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: screenSize().width - 53.4)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(16.7)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// LiveRoomProfileItemTitleView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/14.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomProfileItemTitleView: View {
|
||||
|
||||
let title: String
|
||||
let count: Int?
|
||||
let totalCount: Int?
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
Text(title)
|
||||
.font(.custom(Font.bold.rawValue, size: 13))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
if let count = count {
|
||||
Text("\(count)")
|
||||
.font(.custom(Font.medium.rawValue, size: 13))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.leading, 6.7)
|
||||
}
|
||||
|
||||
if let totalCount = totalCount {
|
||||
Text("/\(totalCount > 9 ? 9 : totalCount - 1)")
|
||||
.font(.custom(Font.medium.rawValue, size: 13))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveRoomProfileItemMasterView: View {
|
||||
|
||||
let id: Int
|
||||
let nickname: String
|
||||
let profileUrl: String
|
||||
let onClickProfile: (Int) -> Void
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
HStack(spacing: 0) {
|
||||
KFImage(URL(string: profileUrl))
|
||||
.resizable()
|
||||
.frame(width: 60, height: 60)
|
||||
.clipShape(Circle())
|
||||
.onTapGesture { onClickProfile(id) }
|
||||
|
||||
Image("ic_crown")
|
||||
.padding(.leading, 16.7)
|
||||
|
||||
Text(nickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 14))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(Color(hex: "909090").opacity(0.3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveRoomProfileItemUserView: View {
|
||||
let isStaff: Bool
|
||||
let userId: Int
|
||||
let nickname: String
|
||||
let profileUrl: String
|
||||
let role: LiveRoomMemberRole
|
||||
|
||||
let onClickChangeListener: (Int) -> Void
|
||||
let onClickInviteSpeaker: (Int) -> Void
|
||||
let onClickKickOut: (Int) -> Void
|
||||
let onClickProfile: (Int) -> Void
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VStack(spacing: 10) {
|
||||
HStack(spacing: 0) {
|
||||
KFImage(URL(string: profileUrl))
|
||||
.resizable()
|
||||
.frame(width: 46.7, height: 46.7)
|
||||
.clipShape(Circle())
|
||||
.onTapGesture { onClickProfile(userId) }
|
||||
|
||||
if role == .MANAGER {
|
||||
Image("ic_badge_manager")
|
||||
.padding(.leading, 16.7)
|
||||
|
||||
Text(nickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 14))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.padding(.leading, 4)
|
||||
.padding(.trailing, 10)
|
||||
} else {
|
||||
Text(nickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 14))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.padding(.horizontal, 10)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
if role == .LISTENER && isStaff {
|
||||
Text("스피커로 초대")
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
.padding(.horizontal, 5.5)
|
||||
.padding(.vertical, 12)
|
||||
.background(Color(hex: "9970ff").opacity(0.3))
|
||||
.cornerRadius(6.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.stroke(Color(hex: "9970ff"), lineWidth: 1)
|
||||
)
|
||||
.onTapGesture {
|
||||
onClickInviteSpeaker(userId)
|
||||
}
|
||||
}
|
||||
|
||||
if role == .SPEAKER && (userId == UserDefaults.int(forKey: .userId) || isStaff) {
|
||||
Text("리스너로 변경")
|
||||
.font(.custom(Font.medium.rawValue, size: 10))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
.padding(.horizontal, 5.5)
|
||||
.padding(.vertical, 12)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(6.7)
|
||||
.onTapGesture {
|
||||
onClickChangeListener(userId)
|
||||
}
|
||||
}
|
||||
|
||||
if role != .MANAGER && isStaff {
|
||||
Image("ic_kick_out")
|
||||
.padding(.leading, 10)
|
||||
.onTapGesture {
|
||||
onClickKickOut(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(Color(hex: "909090").opacity(0.3))
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveRoomProfileRequestSpeakerView: View {
|
||||
|
||||
let onClickRequestSpeaker: () -> Void
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 6.7) {
|
||||
Spacer()
|
||||
Image("ic_request_speak")
|
||||
Text("스피커 요청하기")
|
||||
.font(.custom(Font.bold.rawValue, size: 13.3))
|
||||
.foregroundColor(.white)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 5.3)
|
||||
.stroke(Color(hex: "909090"), lineWidth: 1)
|
||||
)
|
||||
.onTapGesture {
|
||||
onClickRequestSpeaker()
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
}
|
||||
}
|
@@ -0,0 +1,249 @@
|
||||
//
|
||||
// LiveRoomProfilesDialogView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/14.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomProfilesDialogView: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
|
||||
let viewModel: LiveRoomViewModel
|
||||
let roomInfo: GetRoomInfoResponse
|
||||
|
||||
var profiles: [AnyView] = []
|
||||
let accountId = UserDefaults.int(forKey: .userId)
|
||||
|
||||
init(
|
||||
isShowing: Binding<Bool>,
|
||||
viewModel: LiveRoomViewModel,
|
||||
roomInfo: GetRoomInfoResponse,
|
||||
isShowRequestSpeaker: Bool,
|
||||
onClickRequestSpeaker: @escaping () -> Void,
|
||||
registerNotification: @escaping () -> Void,
|
||||
unRegisterNotification: @escaping () -> Void,
|
||||
onClickProfile: @escaping (Int) -> Void
|
||||
) {
|
||||
self._isShowing = isShowing
|
||||
self.viewModel = viewModel
|
||||
self.roomInfo = roomInfo
|
||||
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemTitleView(
|
||||
title: "스탭",
|
||||
count: roomInfo.managerList.count,
|
||||
totalCount: nil
|
||||
)
|
||||
.padding(.vertical, 14)
|
||||
)
|
||||
)
|
||||
|
||||
let isStaff = viewModel.isEqualToStaffId(creatorId: UserDefaults.int(forKey: .userId)) ||
|
||||
roomInfo.creatorId == UserDefaults.int(forKey: .userId)
|
||||
|
||||
for manager in roomInfo.managerList {
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemUserView(
|
||||
isStaff: isStaff ,
|
||||
userId: manager.id,
|
||||
nickname: manager.nickname,
|
||||
profileUrl: manager.profileImage,
|
||||
role: manager.role,
|
||||
onClickChangeListener: { _ in },
|
||||
onClickInviteSpeaker: { _ in },
|
||||
onClickKickOut: { _ in },
|
||||
onClickProfile: onClickProfile
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemTitleView(
|
||||
title: "스피커",
|
||||
count: roomInfo.speakerList.count - 1,
|
||||
totalCount: roomInfo.totalAvailableParticipantsCount
|
||||
)
|
||||
.padding(.vertical, 14)
|
||||
)
|
||||
)
|
||||
|
||||
for speaker in roomInfo.speakerList {
|
||||
if speaker.id == roomInfo.creatorId {
|
||||
self.profiles.insert(
|
||||
AnyView(
|
||||
LiveRoomProfileItemMasterView(
|
||||
id: speaker.id,
|
||||
nickname: speaker.nickname,
|
||||
profileUrl: speaker.profileImage,
|
||||
onClickProfile: onClickProfile
|
||||
)
|
||||
),
|
||||
at: 0
|
||||
)
|
||||
} else {
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemUserView(
|
||||
isStaff: isStaff,
|
||||
userId: speaker.id,
|
||||
nickname: speaker.nickname,
|
||||
profileUrl: speaker.profileImage,
|
||||
role: speaker.role,
|
||||
onClickChangeListener: {
|
||||
if $0 == UserDefaults.int(forKey: .userId) {
|
||||
viewModel.setListener()
|
||||
return
|
||||
}
|
||||
|
||||
viewModel.changeListener(peerId: $0)
|
||||
},
|
||||
onClickInviteSpeaker: { _ in },
|
||||
onClickKickOut: {
|
||||
viewModel.kickOutId = $0
|
||||
viewModel.isShowKickOutPopup = true
|
||||
},
|
||||
onClickProfile: onClickProfile
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if isShowRequestSpeaker {
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileRequestSpeakerView {
|
||||
onClickRequestSpeaker()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemTitleView(
|
||||
title: "리스너",
|
||||
count: nil,
|
||||
totalCount: nil
|
||||
)
|
||||
.padding(.top, 20)
|
||||
.padding(.bottom, 14)
|
||||
)
|
||||
)
|
||||
|
||||
for listener in roomInfo.listenerList {
|
||||
self.profiles.append(
|
||||
AnyView(
|
||||
LiveRoomProfileItemUserView(
|
||||
isStaff: isStaff,
|
||||
userId: listener.id,
|
||||
nickname: listener.nickname,
|
||||
profileUrl: listener.profileImage,
|
||||
role: listener.role,
|
||||
onClickChangeListener: { _ in },
|
||||
onClickInviteSpeaker: {
|
||||
if viewModel.liveRoomInfo!.speakerList.count <= 9 {
|
||||
viewModel.inviteSpeaker(peerId: $0)
|
||||
viewModel.popupContent = "스피커 요청을 보냈습니다.\n잠시만 기다려 주세요."
|
||||
viewModel.isShowPopup = true
|
||||
} else {
|
||||
viewModel.errorMessage = "스피커 정원을 초과했습니다."
|
||||
viewModel.isShowErrorPopup = true
|
||||
}
|
||||
},
|
||||
onClickKickOut: {
|
||||
viewModel.kickOutId = $0
|
||||
viewModel.isShowKickOutPopup = true
|
||||
},
|
||||
onClickProfile: onClickProfile
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VStack(spacing: 16.7) {
|
||||
HStack(spacing: 0) {
|
||||
Text("참여자")
|
||||
.font(.custom(Font.bold.rawValue, size: 15))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("\(roomInfo.participantsCount)")
|
||||
.font(.custom(Font.medium.rawValue, size: 14))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.padding(.leading, 6.7)
|
||||
|
||||
Text("/\(roomInfo.totalAvailableParticipantsCount)")
|
||||
.font(.custom(Font.medium.rawValue, size: 14))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_close_white")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
.onTapGesture { isShowing = false }
|
||||
}
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
ForEach(0..<profiles.count, id: \.self) { index in
|
||||
profiles[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 26.7)
|
||||
.padding(.horizontal, 13.3)
|
||||
.background(Color(hex: "222222").edgesIgnoringSafeArea(.all))
|
||||
.cornerRadius(16.7)
|
||||
|
||||
if viewModel.isShowPopup {
|
||||
LiveRoomDialogView(
|
||||
content: viewModel.popupContent,
|
||||
cancelTitle: viewModel.popupCancelTitle,
|
||||
cancelAction: viewModel.popupCancelAction,
|
||||
confirmTitle: viewModel.popupConfirmTitle,
|
||||
confirmAction: viewModel.popupConfirmAction
|
||||
).onAppear {
|
||||
if viewModel.popupConfirmTitle == nil && viewModel.popupConfirmAction == nil {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
viewModel.isShowPopup = false
|
||||
viewModel.popupCancelTitle = nil
|
||||
viewModel.popupCancelAction = nil
|
||||
viewModel.popupConfirmTitle = nil
|
||||
viewModel.popupConfirmAction = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if viewModel.isShowKickOutPopup {
|
||||
SodaDialog(
|
||||
title: "내보내기",
|
||||
desc: viewModel.kickOutDesc,
|
||||
confirmButtonTitle: "내보내기",
|
||||
confirmButtonAction: {
|
||||
viewModel.kickOut()
|
||||
},
|
||||
cancelButtonTitle: "취소",
|
||||
cancelButtonAction: {
|
||||
viewModel.isShowKickOutPopup = false
|
||||
viewModel.kickOutDesc = ""
|
||||
viewModel.kickOutId = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// LiveRoomUserProfileDialogView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/15.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct LiveRoomUserProfileDialogView: View {
|
||||
|
||||
@Binding var isShowing: Bool
|
||||
|
||||
@State private var introduceLineLimit: Int? = 2
|
||||
|
||||
let viewModel: LiveRoomViewModel
|
||||
let userProfile: GetLiveRoomUserProfileResponse
|
||||
let onClickSetManager: (Int) -> Void
|
||||
let onClickReleaseManager: (Int) -> Void
|
||||
let onClickFollow: (Int) -> Void
|
||||
let onClickUnFollow: (Int) -> Void
|
||||
let onClickInviteSpeaker: (Int) -> Void
|
||||
let onClickChangeListener: (Int) -> Void
|
||||
let onClickMenu: (Int, String, Bool) -> Void
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("프로필")
|
||||
.font(.custom(Font.bold.rawValue, size: 15))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_close_white")
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
.padding(.top, 13.3)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(spacing: 8) {
|
||||
Text(userProfile.nickname)
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text(userProfile.gender)
|
||||
.font(.custom(Font.medium.rawValue, size: 11.3))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
.padding(.horizontal, 5.3)
|
||||
.padding(.vertical, 3)
|
||||
.background(Color(hex: "555555"))
|
||||
.cornerRadius(23.3)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_seemore_vertical")
|
||||
.onTapGesture {
|
||||
onClickMenu(
|
||||
userProfile.userId,
|
||||
userProfile.nickname,
|
||||
userProfile.isBlock
|
||||
)
|
||||
}
|
||||
}
|
||||
.padding(.top, 21.3)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
if let isFollwing = userProfile.isFollowing {
|
||||
if isFollwing {
|
||||
HStack(spacing: 4) {
|
||||
Image("ic_alarm_selected")
|
||||
.resizable()
|
||||
.frame(width: 18.7, height: 18.7)
|
||||
|
||||
Text("팔로잉")
|
||||
.font(.custom(Font.bold.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
}
|
||||
.padding(.vertical, 7.3)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color(hex: "3e1b93"))
|
||||
.cornerRadius(16.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16.7)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture { onClickUnFollow(userProfile.userId) }
|
||||
} else {
|
||||
HStack(spacing: 4) {
|
||||
Image("ic_alarm")
|
||||
.resizable()
|
||||
.frame(width: 18.7, height: 18.7)
|
||||
|
||||
Text("팔로우")
|
||||
.font(.custom(Font.bold.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
}
|
||||
.padding(.vertical, 7.3)
|
||||
.frame(maxWidth: .infinity)
|
||||
.cornerRadius(16.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16.7)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture { onClickFollow(userProfile.userId) }
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 4) {
|
||||
Image("ic_message_send")
|
||||
.resizable()
|
||||
.frame(width: 18.7, height: 18.7)
|
||||
|
||||
Text("메시지 보내기")
|
||||
.font(.custom(Font.bold.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "ffffff"))
|
||||
}
|
||||
.padding(.vertical, 7.3)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color(hex: "9970ff"))
|
||||
.cornerRadius(16.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .writeTextMessage(
|
||||
userId: userProfile.userId,
|
||||
nickname: userProfile.nickname))
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.top, 21.3)
|
||||
|
||||
KFImage(URL(string: userProfile.profileUrl))
|
||||
.resizable()
|
||||
.aspectRatio(CGSize(width: 1, height: 1), contentMode: .fill)
|
||||
.cornerRadius(8)
|
||||
.padding(.top, 21.3)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
if let isSpeaker = userProfile.isSpeaker {
|
||||
Text(isSpeaker ? "리스너 변경" : "스피커 초대")
|
||||
.font(.custom(Font.bold.rawValue, size: 15))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13)
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture {
|
||||
if isSpeaker {
|
||||
onClickChangeListener(userProfile.userId)
|
||||
} else {
|
||||
onClickInviteSpeaker(userProfile.userId)
|
||||
}
|
||||
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
if let isManager = userProfile.isManager {
|
||||
Text(isManager ? "스탭 해제" : "스탭 지정")
|
||||
.font(.custom(Font.bold.rawValue, size: 15))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13)
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture {
|
||||
if isManager {
|
||||
onClickReleaseManager(userProfile.userId)
|
||||
} else {
|
||||
onClickSetManager(userProfile.userId)
|
||||
}
|
||||
|
||||
isShowing = false
|
||||
}
|
||||
}
|
||||
|
||||
if (userProfile.isSpeaker != nil && !viewModel.isEqualToStaffId(creatorId: userProfile.userId)) ||
|
||||
(userProfile.isSpeaker != nil && userProfile.isManager != nil) {
|
||||
Text("내보내기")
|
||||
.font(.custom(Font.bold.rawValue, size: 15))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13)
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
)
|
||||
.onTapGesture {
|
||||
viewModel.kickOutId = userProfile.userId
|
||||
viewModel.isShowKickOutPopup = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.top, 21.3)
|
||||
|
||||
Text(userProfile.tags)
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "9970ff"))
|
||||
.lineSpacing(3)
|
||||
.padding(.top, 21.3)
|
||||
|
||||
Text(userProfile.introduce)
|
||||
.font(.custom(Font.medium.rawValue, size: 12))
|
||||
.foregroundColor(Color(hex: "909090"))
|
||||
.lineLimit(introduceLineLimit)
|
||||
.lineSpacing(3)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.vertical, 20)
|
||||
.onTapGesture {
|
||||
if let _ = introduceLineLimit {
|
||||
self.introduceLineLimit = nil
|
||||
} else {
|
||||
self.introduceLineLimit = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.background(Color(hex: "222222").edgesIgnoringSafeArea(.all))
|
||||
.cornerRadius(8)
|
||||
|
||||
if viewModel.isShowKickOutPopup {
|
||||
SodaDialog(
|
||||
title: "내보내기",
|
||||
desc: viewModel.kickOutDesc,
|
||||
confirmButtonTitle: "내보내기",
|
||||
confirmButtonAction: {
|
||||
viewModel.kickOut()
|
||||
isShowing = false
|
||||
},
|
||||
cancelButtonTitle: "취소",
|
||||
cancelButtonAction: {
|
||||
viewModel.isShowKickOutPopup = false
|
||||
viewModel.kickOutDesc = ""
|
||||
viewModel.kickOutId = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user