feat(creator): 라이브 탭 UI를 마무리한다

This commit is contained in:
Yu Sung
2026-07-04 03:20:46 +09:00
parent abc10d7610
commit b6580e201f
11 changed files with 109 additions and 92 deletions

View File

@@ -66,8 +66,7 @@ struct CreatorChannelFloatingActionMenu: View {
}
}
}
.padding(.trailing, SodaSpacing.s20)
.padding(.bottom, SodaSpacing.s32)
.padding(.trailing, SodaSpacing.s14)
.animation(animation, value: isPresented)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)

View File

@@ -1,22 +1,11 @@
import SwiftUI
struct CreatorChannelSortBar: View {
let totalCount: Int
let selectedSort: ContentSort
let onTapSort: () -> Void
var body: some View {
HStack(alignment: .center, spacing: SodaSpacing.s8) {
HStack(spacing: SodaSpacing.s4) {
Text(I18n.CreatorChannelLive.totalLabel)
.appFont(size: 14, weight: .medium)
.foregroundColor(Color.gray500)
Text(totalCount.comma())
.appFont(size: 14, weight: .medium)
.foregroundColor(Color.gray400)
}
Spacer()
Button(action: onTapSort) {
@@ -25,9 +14,8 @@ struct CreatorChannelSortBar: View {
.appFont(size: 14, weight: .medium)
.foregroundColor(Color.white)
Image(systemName: "chevron.down")
Image("ic_new_sort")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(Color.gray400)
}
.contentShape(Rectangle())
}
@@ -41,7 +29,7 @@ struct CreatorChannelSortBar: View {
struct CreatorChannelSortBar_Previews: PreviewProvider {
static var previews: some View {
CreatorChannelSortBar(totalCount: 100, selectedSort: .latest, onTapSort: {})
CreatorChannelSortBar(selectedSort: .latest, onTapSort: {})
.previewLayout(.sizeThatFits)
}
}

View File

@@ -95,6 +95,15 @@ struct CreatorChannelView: View {
)
}
if isOwnCreatorChannel && viewModel.selectedTab == .live && !viewModel.isLoading {
VStack {
Spacer()
CreatorChannelLiveStartButton(action: showCreateLive)
}
.ignoresSafeArea(.container, edges: .bottom)
}
if isShowAuthConfirmView {
authConfirmDialog
}
@@ -191,7 +200,14 @@ struct CreatorChannelView: View {
@ViewBuilder
private var selectedTabContent: some View {
if viewModel.selectedTab != .home {
if viewModel.selectedTab == .live {
CreatorChannelLiveTabView(
creatorId: creatorId,
isOwnCreatorChannel: isOwnCreatorChannel,
onTapLive: showLiveDetail,
onTapContent: showContentDetail
)
} else if viewModel.selectedTab != .home {
CreatorChannelPlaceholderTabView(title: viewModel.selectedTab.title)
} else if let response = viewModel.response {
CreatorChannelHomeView(

View File

@@ -4,24 +4,30 @@ struct CreatorChannelLiveStartButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
HStack(spacing: SodaSpacing.s6) {
Image("ic_new_create_live")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
Text(I18n.CreatorChannelLive.startLive)
.appFont(size: 16, weight: .bold)
.foregroundColor(.white)
.lineLimit(1)
VStack {
Button(action: action) {
HStack(spacing: SodaSpacing.s6) {
Image("ic_new_create_live")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
Text(I18n.CreatorChannelLive.startLive)
.appFont(size: 16, weight: .bold)
.foregroundColor(.white)
.lineLimit(1)
}
.frame(maxWidth: .infinity)
.frame(height: 52)
.padding(.horizontal, SodaSpacing.s14)
.background(Color.soda400)
.clipShape(Capsule())
}
.frame(maxWidth: .infinity)
.frame(height: 56)
.background(Color.soda400)
.clipShape(Capsule())
.buttonStyle(.plain)
}
.buttonStyle(.plain)
.padding(.top, SodaSpacing.s14)
.padding(.bottom, 34)
.background(Color.black)
}
}

View File

@@ -5,21 +5,12 @@ struct CreatorChannelLiveTabView: View {
let isOwnCreatorChannel: Bool
let onTapLive: (Int) -> Void
let onTapContent: (Int) -> Void
let onTapCreateLive: () -> Void
@StateObject private var viewModel = CreatorChannelLiveViewModel()
@State private var isSortSheetPresented = false
var body: some View {
ZStack(alignment: .bottom) {
content
if isOwnCreatorChannel {
CreatorChannelLiveStartButton(action: onTapCreateLive)
.padding(.horizontal, SodaSpacing.s20)
.padding(.bottom, SodaSpacing.s20)
}
}
content
.background(Color.black)
.onAppear {
if viewModel.hasLoaded == false {
@@ -38,7 +29,6 @@ struct CreatorChannelLiveTabView: View {
private var content: some View {
VStack(spacing: 0) {
CreatorChannelSortBar(
totalCount: viewModel.response?.liveReplayContentCount ?? 0,
selectedSort: viewModel.selectedSort,
onTapSort: {
isSortSheetPresented = true
@@ -67,7 +57,7 @@ struct CreatorChannelLiveTabView: View {
.padding(.vertical, SodaSpacing.s20)
}
}
.padding(.bottom, isOwnCreatorChannel ? 96 : SodaSpacing.s20)
.padding(.bottom, isOwnCreatorChannel ? 70 : SodaSpacing.s20)
}
}
}
@@ -78,8 +68,7 @@ struct CreatorChannelLiveTabView_Previews: PreviewProvider {
creatorId: 1,
isOwnCreatorChannel: true,
onTapLive: { _ in },
onTapContent: { _ in },
onTapCreateLive: {}
onTapContent: { _ in }
)
.background(Color.black)
.previewLayout(.sizeThatFits)

View File

@@ -3,7 +3,6 @@ import Foundation
enum ContentSort: String, Decodable, CaseIterable, Hashable {
case latest = "LATEST"
case popular = "POPULAR"
case owned = "OWNED"
case priceHigh = "PRICE_HIGH"
case priceLow = "PRICE_LOW"
@@ -13,8 +12,6 @@ enum ContentSort: String, Decodable, CaseIterable, Hashable {
return I18n.CreatorChannelLive.Sort.latest
case .popular:
return I18n.CreatorChannelLive.Sort.popular
case .owned:
return I18n.CreatorChannelLive.Sort.owned
case .priceHigh:
return I18n.CreatorChannelLive.Sort.priceHigh
case .priceLow: