홈 - 하단 탭 추가
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_content_normal.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_content_normal.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 2.5 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_content_selected.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_content_selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 2.9 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_explorer_normal.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_explorer_normal.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.1 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_explorer_selected.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_explorer_selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.1 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_live_normal.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_live_normal.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_live_normal.imageset/ic_tabbar_live_normal.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_live_selected.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_live_selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_live_selected.imageset/ic_tabbar_live_selected.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_message_normal.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_message_normal.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.0 KiB |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_message_selected.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_message_selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 998 B |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_my_normal.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_my_normal.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_my_normal.imageset/ic_tabbar_my_normal.png
vendored
Normal file
After Width: | Height: | Size: 928 B |
21
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_my_selected.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ic_tabbar_my_selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
SodaLive/Resources/Assets.xcassets/Tab/ic_tabbar_my_selected.imageset/ic_tabbar_my_selected.png
vendored
Normal file
After Width: | Height: | Size: 925 B |
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// ContentMainView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentMainView: View {
|
||||
var body: some View {
|
||||
Text("Content")
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentMainView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentMainView()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// ExplorerView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ExplorerView: View {
|
||||
var body: some View {
|
||||
Text("Explorer")
|
||||
}
|
||||
}
|
||||
|
||||
struct ExplorerView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ExplorerView()
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// HomeView.swift
|
||||
// LiveView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
|
@ -7,14 +7,14 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
struct HomeView: View {
|
||||
struct LiveView: View {
|
||||
var body: some View {
|
||||
Text("Home View")
|
||||
Text("Live")
|
||||
}
|
||||
}
|
||||
|
||||
struct HomeView_Previews: PreviewProvider {
|
||||
struct LiveView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
HomeView()
|
||||
LiveView()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
//
|
||||
// BottomTabView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct BottomTabView: View {
|
||||
let width: CGFloat
|
||||
@Binding var currentTab: HomeViewModel.CurrentTab
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
let tabWidth = width / 5
|
||||
|
||||
TabButton(
|
||||
title: "라이브",
|
||||
action: {
|
||||
if currentTab != .live {
|
||||
currentTab = .live
|
||||
}
|
||||
},
|
||||
image: {
|
||||
currentTab == .live ?
|
||||
"ic_tabbar_live_selected" :
|
||||
"ic_tabbar_live_normal"
|
||||
},
|
||||
fontName: {
|
||||
currentTab == .live ?
|
||||
Font.bold.rawValue :
|
||||
Font.medium.rawValue
|
||||
},
|
||||
color: {
|
||||
currentTab == .live ?
|
||||
Color(hex: "9970ff") :
|
||||
Color(hex: "909090")
|
||||
},
|
||||
width: tabWidth
|
||||
)
|
||||
|
||||
TabButton(
|
||||
title: "콘텐츠",
|
||||
action: {
|
||||
if currentTab != .content {
|
||||
currentTab = .content
|
||||
}
|
||||
},
|
||||
image: {
|
||||
currentTab == .content ?
|
||||
"ic_tabbar_content_selected" :
|
||||
"ic_tabbar_content_normal"
|
||||
},
|
||||
fontName: {
|
||||
currentTab == .content ?
|
||||
Font.bold.rawValue :
|
||||
Font.medium.rawValue
|
||||
},
|
||||
color: {
|
||||
currentTab == .content ?
|
||||
Color(hex: "9970ff") :
|
||||
Color(hex: "909090")
|
||||
},
|
||||
width: tabWidth
|
||||
)
|
||||
|
||||
TabButton(
|
||||
title: "탐색",
|
||||
action: {
|
||||
if currentTab != .explorer {
|
||||
currentTab = .explorer
|
||||
}
|
||||
},
|
||||
image: {
|
||||
currentTab == .explorer ?
|
||||
"ic_tabbar_explorer_selected" :
|
||||
"ic_tabbar_explorer_normal"
|
||||
},
|
||||
fontName: {
|
||||
currentTab == .explorer ?
|
||||
Font.bold.rawValue :
|
||||
Font.medium.rawValue
|
||||
},
|
||||
color: {
|
||||
currentTab == .explorer ?
|
||||
Color(hex: "9970ff") :
|
||||
Color(hex: "909090")
|
||||
},
|
||||
width: tabWidth
|
||||
)
|
||||
|
||||
TabButton(
|
||||
title: "메시지",
|
||||
action: {
|
||||
if currentTab != .message {
|
||||
currentTab = .message
|
||||
}
|
||||
},
|
||||
image: {
|
||||
currentTab == .message ?
|
||||
"ic_tabbar_message_selected" :
|
||||
"ic_tabbar_message_normal"
|
||||
},
|
||||
fontName: {
|
||||
currentTab == .message ?
|
||||
Font.bold.rawValue :
|
||||
Font.medium.rawValue
|
||||
},
|
||||
color: {
|
||||
currentTab == .message ?
|
||||
Color(hex: "9970ff") :
|
||||
Color(hex: "909090")
|
||||
},
|
||||
width: tabWidth
|
||||
)
|
||||
|
||||
TabButton(
|
||||
title: "마이",
|
||||
action: {
|
||||
if currentTab != .mypage {
|
||||
currentTab = .mypage
|
||||
}
|
||||
},
|
||||
image: {
|
||||
currentTab == .mypage ?
|
||||
"ic_tabbar_my_selected" :
|
||||
"ic_tabbar_my_normal"
|
||||
},
|
||||
fontName: {
|
||||
currentTab == .mypage ?
|
||||
Font.bold.rawValue :
|
||||
Font.medium.rawValue
|
||||
},
|
||||
color: {
|
||||
currentTab == .mypage ?
|
||||
Color(hex: "9970ff") :
|
||||
Color(hex: "909090")
|
||||
},
|
||||
width: tabWidth
|
||||
)
|
||||
}
|
||||
.background(Color(hex: "111111"))
|
||||
}
|
||||
}
|
||||
|
||||
struct BottomTabView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
BottomTabView(
|
||||
width: UIScreen.main.bounds.width,
|
||||
currentTab: .constant(.live)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// HomeView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
import Firebase
|
||||
import Kingfisher
|
||||
|
||||
struct HomeView: View {
|
||||
|
||||
@StateObject var viewModel = HomeViewModel()
|
||||
@StateObject var appState = AppState.shared
|
||||
|
||||
private let liveView = LiveView()
|
||||
private let explorer = ExplorerView()
|
||||
private let messageView = MessageView()
|
||||
private let contentView = ContentMainView()
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { proxy in
|
||||
ZStack(alignment: .bottom) {
|
||||
VStack(spacing: 0) {
|
||||
ZStack {
|
||||
contentView
|
||||
.frame(width: viewModel.currentTab == .content ? proxy.size.width : 0)
|
||||
.opacity(viewModel.currentTab == .content ? 1.0 : 0.01)
|
||||
|
||||
liveView
|
||||
.frame(width: viewModel.currentTab == .live ? proxy.size.width : 0)
|
||||
.opacity(viewModel.currentTab == .live ? 1.0 : 0.01)
|
||||
|
||||
explorer
|
||||
.frame(width: viewModel.currentTab == .explorer ? proxy.size.width : 0)
|
||||
.opacity(viewModel.currentTab == .explorer ? 1.0 : 0.01)
|
||||
|
||||
messageView
|
||||
.frame(width: viewModel.currentTab == .message ? proxy.size.width : 0)
|
||||
.opacity(viewModel.currentTab == .message ? 1.0 : 0.01)
|
||||
|
||||
if viewModel.currentTab == .mypage {
|
||||
MyPageView()
|
||||
}
|
||||
}
|
||||
.padding(.bottom, appState.isShowPlayer ? 72 : 0)
|
||||
|
||||
Spacer()
|
||||
|
||||
BottomTabView(width: proxy.size.width, currentTab: $viewModel.currentTab)
|
||||
|
||||
if proxy.safeAreaInsets.bottom > 0 {
|
||||
Rectangle()
|
||||
.foregroundColor(Color(hex: "111111"))
|
||||
.frame(width: proxy.size.width, height: 15.3)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
|
||||
}
|
||||
}
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct HomeView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
HomeView()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// HomeViewModel.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
final class HomeViewModel: ObservableObject {
|
||||
|
||||
private var subscription = Set<AnyCancellable>()
|
||||
|
||||
private let userRepository = UserRepository()
|
||||
|
||||
enum CurrentTab: String {
|
||||
case content, live, explorer, message, mypage
|
||||
}
|
||||
|
||||
@Published var currentTab: CurrentTab = .live
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// TabButton.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TabButton: View {
|
||||
|
||||
let title: String
|
||||
let action: () -> Void
|
||||
let image: () -> String
|
||||
let fontName: () -> String
|
||||
let color: () -> Color
|
||||
let width: CGFloat
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 3.3) {
|
||||
Image(image())
|
||||
|
||||
Text(title)
|
||||
.font(.custom(fontName(), size: 10))
|
||||
.foregroundColor(color())
|
||||
}
|
||||
.frame(width: width)
|
||||
.contentShape(Rectangle())
|
||||
.padding(.vertical, 13.3)
|
||||
.onTapGesture { action() }
|
||||
}
|
||||
}
|
||||
|
||||
struct TabButton_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TabButton(
|
||||
title: "라이브",
|
||||
action: {},
|
||||
image: { "ic_tabbar_live_selected" },
|
||||
fontName: { Font.bold.rawValue },
|
||||
color: { Color(hex: "9970ff") },
|
||||
width: UIScreen.main.bounds.width / 4
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// MessageView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MessageView: View {
|
||||
var body: some View {
|
||||
Text("Message")
|
||||
}
|
||||
}
|
||||
|
||||
struct MessageView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MessageView()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// MyPageView.swift
|
||||
// SodaLive
|
||||
//
|
||||
// Created by klaus on 2023/08/09.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MyPageView: View {
|
||||
var body: some View {
|
||||
Text("MyPage")
|
||||
}
|
||||
}
|
||||
|
||||
struct MyPageView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MyPageView()
|
||||
}
|
||||
}
|