parent
fa94c5447f
commit
80cb19a1c7
21
SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/Contents.json
vendored
Normal file
21
SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "ic_logo_circle_gray.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/ic_logo_circle_gray.png
vendored
Normal file
BIN
SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/ic_logo_circle_gray.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
|
@ -12,6 +12,8 @@ enum AppStep {
|
||||||
|
|
||||||
case main
|
case main
|
||||||
|
|
||||||
|
case login
|
||||||
|
|
||||||
case signUp
|
case signUp
|
||||||
|
|
||||||
case findPassword
|
case findPassword
|
||||||
|
|
|
@ -89,6 +89,12 @@ extension AuditionApi: TargetType {
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers: [String : String]? {
|
var headers: [String : String]? {
|
||||||
|
switch self {
|
||||||
|
case .getAuditionList:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,19 @@ struct AuditionView: View {
|
||||||
|
|
||||||
@StateObject var viewModel = AuditionViewModel()
|
@StateObject var viewModel = AuditionViewModel()
|
||||||
@AppStorage("isAuditionNotification") private var isAuditionNotification: Bool = UserDefaults.bool(forKey: .isAuditionNotification)
|
@AppStorage("isAuditionNotification") private var isAuditionNotification: Bool = UserDefaults.bool(forKey: .isAuditionNotification)
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BaseView(isLoading: $viewModel.isLoading) {
|
BaseView(isLoading: $viewModel.isLoading) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
HomeNavigationBar(title: "오디션") {
|
HomeNavigationBar(title: "오디션") {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
Image(isAuditionNotification ? "btn_audition_notification_selected" : "btn_audition_notification_normal")
|
Image(isAuditionNotification ? "btn_audition_notification_selected" : "btn_audition_notification_normal")
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
viewModel.updateNotificationSettings()
|
viewModel.updateNotificationSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Text("보이스온 오디션 이용방법")
|
Text("보이스온 오디션 이용방법")
|
||||||
|
@ -70,12 +73,17 @@ struct AuditionView: View {
|
||||||
|
|
||||||
AuditionItemView(item: item)
|
AuditionItemView(item: item)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
if !item.isOff {
|
if !item.isOff {
|
||||||
AppState.shared
|
AppState.shared
|
||||||
.setAppStep(
|
.setAppStep(
|
||||||
step: .auditionDetail(auditionId: item.id)
|
step: .auditionDetail(auditionId: item.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if $0 == viewModel.firstIsOffIndex {
|
} else if $0 == viewModel.firstIsOffIndex {
|
||||||
|
@ -104,24 +112,21 @@ struct AuditionView: View {
|
||||||
|
|
||||||
AuditionItemView(item: item)
|
AuditionItemView(item: item)
|
||||||
.padding(.top, 25)
|
.padding(.top, 25)
|
||||||
.onTapGesture {
|
|
||||||
if !item.isOff {
|
|
||||||
AppState.shared
|
|
||||||
.setAppStep(
|
|
||||||
step: .auditionDetail(auditionId: item.id)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AuditionItemView(item: item)
|
AuditionItemView(item: item)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
if !item.isOff {
|
if !item.isOff {
|
||||||
AppState.shared
|
AppState.shared
|
||||||
.setAppStep(
|
.setAppStep(
|
||||||
step: .auditionDetail(auditionId: item.id)
|
step: .auditionDetail(auditionId: item.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ enum ContentApi {
|
||||||
|
|
||||||
case getContentMainHome(isAdultContentVisible: Bool, contentType: ContentType)
|
case getContentMainHome(isAdultContentVisible: Bool, contentType: ContentType)
|
||||||
case getPopularContentByCreator(creatorId: Int, isAdultContentVisible: Bool, contentType: ContentType)
|
case getPopularContentByCreator(creatorId: Int, isAdultContentVisible: Bool, contentType: ContentType)
|
||||||
|
case getContentMainHomeContentRanking(isAdultContentVisible: Bool, contentType: ContentType, sortType: String)
|
||||||
|
|
||||||
case getContentMainSeries(isAdultContentVisible: Bool, contentType: ContentType)
|
case getContentMainSeries(isAdultContentVisible: Bool, contentType: ContentType)
|
||||||
case getRecommendSeriesListByGenre(genreId: Int, isAdultContentVisible: Bool, contentType: ContentType)
|
case getRecommendSeriesListByGenre(genreId: Int, isAdultContentVisible: Bool, contentType: ContentType)
|
||||||
|
@ -168,6 +169,9 @@ extension ContentApi: TargetType {
|
||||||
case .getPopularContentByCreator:
|
case .getPopularContentByCreator:
|
||||||
return "/v2/audio-content/main/home/popular-content-by-creator"
|
return "/v2/audio-content/main/home/popular-content-by-creator"
|
||||||
|
|
||||||
|
case .getContentMainHomeContentRanking:
|
||||||
|
return "/v2/audio-content/main/home/content/ranking"
|
||||||
|
|
||||||
case .getContentMainSeries:
|
case .getContentMainSeries:
|
||||||
return "/v2/audio-content/main/series"
|
return "/v2/audio-content/main/series"
|
||||||
|
|
||||||
|
@ -238,7 +242,7 @@ extension ContentApi: TargetType {
|
||||||
case .getMainBannerList, .getMainOrderList, .getNewContentUploadCreatorList, .getCurationList, .getAudioContentByTheme:
|
case .getMainBannerList, .getMainOrderList, .getNewContentUploadCreatorList, .getCurationList, .getAudioContentByTheme:
|
||||||
return .get
|
return .get
|
||||||
|
|
||||||
case .getContentMainHome, .getPopularContentByCreator, .getContentMainSeries, .getRecommendSeriesListByGenre, .getRecommendSeriesByCreator, .getContentMainContent,
|
case .getContentMainHome, .getPopularContentByCreator, .getContentMainHomeContentRanking, .getContentMainSeries, .getRecommendSeriesListByGenre, .getRecommendSeriesByCreator, .getContentMainContent,
|
||||||
.getContentMainNewContentOfTheme, .getDailyContentRanking, .getRecommendContentByTag, .getContentMainAlarm, .getContentMainAlarmAll,
|
.getContentMainNewContentOfTheme, .getDailyContentRanking, .getRecommendContentByTag, .getContentMainAlarm, .getContentMainAlarmAll,
|
||||||
.getContentMainAsmr, .getPopularAsmrContentByCreator, .getContentMainReplay, .getPopularReplayContentByCreator,
|
.getContentMainAsmr, .getPopularAsmrContentByCreator, .getContentMainReplay, .getPopularReplayContentByCreator,
|
||||||
.getContentMainFree, .getIntroduceCreatorList, .getNewFreeContentOfTheme, .getPopularFreeContentByCreator, .getCompletedSeries, .getContentMainContentPopularContentByCreator:
|
.getContentMainFree, .getIntroduceCreatorList, .getNewFreeContentOfTheme, .getPopularFreeContentByCreator, .getCompletedSeries, .getContentMainContentPopularContentByCreator:
|
||||||
|
@ -439,6 +443,15 @@ extension ContentApi: TargetType {
|
||||||
|
|
||||||
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
|
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
|
||||||
|
|
||||||
|
case .getContentMainHomeContentRanking(let isAdultContentVisible, let contentType, let sortType):
|
||||||
|
let parameters = [
|
||||||
|
"sort-type": sortType,
|
||||||
|
"isAdultContentVisible": isAdultContentVisible,
|
||||||
|
"contentType": contentType
|
||||||
|
] as [String : Any]
|
||||||
|
|
||||||
|
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
|
||||||
|
|
||||||
case .getRecommendSeriesByCreator(let creatorId, let isAdultContentVisible, let contentType):
|
case .getRecommendSeriesByCreator(let creatorId, let isAdultContentVisible, let contentType):
|
||||||
let parameters = [
|
let parameters = [
|
||||||
"creatorId": creatorId,
|
"creatorId": creatorId,
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Kingfisher
|
||||||
|
|
||||||
struct ContentMainTabRankContentView: View {
|
struct ContentMainTabRankContentView: View {
|
||||||
|
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
let rows = [
|
let rows = [
|
||||||
GridItem(.fixed(60), alignment: .leading),
|
GridItem(.fixed(60), alignment: .leading),
|
||||||
GridItem(.fixed(60), alignment: .leading),
|
GridItem(.fixed(60), alignment: .leading),
|
||||||
|
@ -92,9 +94,13 @@ struct ContentMainTabRankContentView: View {
|
||||||
.frame(width: screenSize().width * 0.66, alignment: .leading)
|
.frame(width: screenSize().width * 0.66, alignment: .leading)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
.shared
|
AppState.shared
|
||||||
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import Kingfisher
|
||||||
|
|
||||||
struct ContentByChannelView: View {
|
struct ContentByChannelView: View {
|
||||||
|
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
let title: String
|
let title: String
|
||||||
let creatorList: [ContentCreatorResponse]
|
let creatorList: [ContentCreatorResponse]
|
||||||
let contentList: [GetAudioContentRankingItem]
|
let contentList: [GetAudioContentRankingItem]
|
||||||
|
@ -111,15 +113,23 @@ struct ContentByChannelView: View {
|
||||||
.foregroundColor(.gray77)
|
.foregroundColor(.gray77)
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
.shared
|
AppState.shared
|
||||||
.setAppStep(step: .creatorDetail(userId: content.creatorId))
|
.setAppStep(step: .creatorDetail(userId: content.creatorId))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
.shared
|
AppState.shared
|
||||||
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,4 +31,14 @@ class ContentMainTabHomeRepository {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getContentRanking(sortType: String = "매출") -> AnyPublisher<Response, MoyaError> {
|
||||||
|
return api.requestPublisher(
|
||||||
|
.getContentMainHomeContentRanking(
|
||||||
|
isAdultContentVisible: UserDefaults.isAdultContentVisible(),
|
||||||
|
contentType: ContentType(rawValue: UserDefaults.string(forKey: .contentPreference)) ?? ContentType.ALL,
|
||||||
|
sortType: sortType
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import SwiftUI
|
||||||
struct ContentMainTabHomeView: View {
|
struct ContentMainTabHomeView: View {
|
||||||
|
|
||||||
@StateObject var viewModel = ContentMainTabHomeViewModel()
|
@StateObject var viewModel = ContentMainTabHomeViewModel()
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BaseView(isLoading: $viewModel.isLoading) {
|
BaseView(isLoading: $viewModel.isLoading) {
|
||||||
|
@ -29,11 +30,13 @@ struct ContentMainTabHomeView: View {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
Image("ic_content_keep")
|
Image("ic_content_keep")
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
|
|
||||||
if let notice = viewModel.noticeItem {
|
if let notice = viewModel.noticeItem {
|
||||||
|
@ -45,12 +48,14 @@ struct ContentMainTabHomeView: View {
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
}
|
}
|
||||||
|
|
||||||
if viewModel.bannerList.count > 0 {
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||||
|
viewModel.bannerList.count > 0 {
|
||||||
ContentMainBannerViewV2(bannerList: viewModel.bannerList)
|
ContentMainBannerViewV2(bannerList: viewModel.bannerList)
|
||||||
.padding(.top, 30)
|
.padding(.top, 30)
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Image("ic_title_search_black")
|
Image("ic_title_search_black")
|
||||||
|
|
||||||
|
@ -192,6 +197,7 @@ struct ContentMainTabHomeView: View {
|
||||||
.cornerRadius(5.3)
|
.cornerRadius(5.3)
|
||||||
.padding(.top, 30)
|
.padding(.top, 30)
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
|
}
|
||||||
|
|
||||||
if let response = viewModel.rankCreatorResponse {
|
if let response = viewModel.rankCreatorResponse {
|
||||||
ContentMainTabHomeRankCreatorView(response: response)
|
ContentMainTabHomeRankCreatorView(response: response)
|
||||||
|
@ -210,7 +216,11 @@ struct ContentMainTabHomeView: View {
|
||||||
title: "인기 단편",
|
title: "인기 단편",
|
||||||
isMore: true,
|
isMore: true,
|
||||||
onClickMore: {
|
onClickMore: {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .contentRankingAll)
|
AppState.shared.setAppStep(step: .contentRankingAll)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
sortList: !viewModel.rankSortTypeList.isEmpty ?
|
sortList: !viewModel.rankSortTypeList.isEmpty ?
|
||||||
viewModel.rankSortTypeList :
|
viewModel.rankSortTypeList :
|
||||||
|
@ -221,7 +231,8 @@ struct ContentMainTabHomeView: View {
|
||||||
.padding(.top, 30)
|
.padding(.top, 30)
|
||||||
}
|
}
|
||||||
|
|
||||||
if viewModel.eventBannerList.count > 0 {
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||||
|
viewModel.eventBannerList.count > 0 {
|
||||||
SectionEventBannerView(items: viewModel.eventBannerList)
|
SectionEventBannerView(items: viewModel.eventBannerList)
|
||||||
.padding(.top, 30)
|
.padding(.top, 30)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import Combine
|
||||||
final class ContentMainTabHomeViewModel: ObservableObject {
|
final class ContentMainTabHomeViewModel: ObservableObject {
|
||||||
|
|
||||||
private let repository = ContentMainTabHomeRepository()
|
private let repository = ContentMainTabHomeRepository()
|
||||||
private let contentRepository = ContentRepository()
|
|
||||||
private var subscription = Set<AnyCancellable>()
|
private var subscription = Set<AnyCancellable>()
|
||||||
|
|
||||||
@Published var errorMessage = ""
|
@Published var errorMessage = ""
|
||||||
|
@ -77,7 +76,7 @@ final class ContentMainTabHomeViewModel: ObservableObject {
|
||||||
|
|
||||||
func getContentRanking(sort: String = "매출") {
|
func getContentRanking(sort: String = "매출") {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
contentRepository.getContentRanking(page: 1, size: 12, sortType: sort)
|
repository.getContentRanking(sortType: sort)
|
||||||
.sink { result in
|
.sink { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .finished:
|
case .finished:
|
||||||
|
@ -90,10 +89,10 @@ final class ContentMainTabHomeViewModel: ObservableObject {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let jsonDecoder = JSONDecoder()
|
let jsonDecoder = JSONDecoder()
|
||||||
let decoded = try jsonDecoder.decode(ApiResponse<GetAudioContentRanking>.self, from: responseData)
|
let decoded = try jsonDecoder.decode(ApiResponse<[GetAudioContentRankingItem]>.self, from: responseData)
|
||||||
|
|
||||||
if let data = decoded.data, decoded.success {
|
if let data = decoded.data, decoded.success {
|
||||||
self.rankContentList = data.items
|
self.rankContentList = data
|
||||||
} else {
|
} else {
|
||||||
if let message = decoded.message {
|
if let message = decoded.message {
|
||||||
self.errorMessage = message
|
self.errorMessage = message
|
||||||
|
|
|
@ -10,6 +10,8 @@ import Kingfisher
|
||||||
|
|
||||||
struct ContentMainTabHomeRankCreatorView: View {
|
struct ContentMainTabHomeRankCreatorView: View {
|
||||||
|
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
let response: GetExplorerSectionResponse
|
let response: GetExplorerSectionResponse
|
||||||
|
|
||||||
let rankingCrawns = ["ic_crown_1", "ic_crown_2", "ic_crown_3"]
|
let rankingCrawns = ["ic_crown_1", "ic_crown_2", "ic_crown_3"]
|
||||||
|
@ -121,8 +123,13 @@ struct ContentMainTabHomeRankCreatorView: View {
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared
|
AppState.shared
|
||||||
.setAppStep(step: .creatorDetail(userId: creator.id))
|
.setAppStep(step: .creatorDetail(userId: creator.id))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,16 @@ struct ContentView: View {
|
||||||
if appState.isChangeAdultContentVisible {
|
if appState.isChangeAdultContentVisible {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
} else {
|
} else {
|
||||||
MainView()
|
HomeView()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch appState.appStep {
|
switch appState.appStep {
|
||||||
case .splash:
|
case .splash:
|
||||||
SplashView()
|
SplashView()
|
||||||
|
|
||||||
|
case .login:
|
||||||
|
LoginView()
|
||||||
|
|
||||||
case .signUp:
|
case .signUp:
|
||||||
SignUpView()
|
SignUpView()
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct SectionEventBannerView: View {
|
||||||
|
|
||||||
@State private var currentIndex = 0
|
@State private var currentIndex = 0
|
||||||
@State private var timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
|
@State private var timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
let items: [EventItem]
|
let items: [EventItem]
|
||||||
|
|
||||||
|
@ -38,11 +39,15 @@ struct SectionEventBannerView: View {
|
||||||
)
|
)
|
||||||
.tag(index)
|
.tag(index)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
if let _ = item.detailImageUrl {
|
if let _ = item.detailImageUrl {
|
||||||
AppState.shared.setAppStep(step: .eventDetail(event: item))
|
AppState.shared.setAppStep(step: .eventDetail(event: item))
|
||||||
} else if let link = item.link, link.trimmingCharacters(in: .whitespaces).count > 0, let url = URL(string: link), UIApplication.shared.canOpenURL(url) {
|
} else if let link = item.link, link.trimmingCharacters(in: .whitespaces).count > 0, let url = URL(string: link), UIApplication.shared.canOpenURL(url) {
|
||||||
UIApplication.shared.open(url)
|
UIApplication.shared.open(url)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
KFImage(URL(string: item.thumbnailImageUrl))
|
KFImage(URL(string: item.thumbnailImageUrl))
|
||||||
|
@ -62,11 +67,15 @@ struct SectionEventBannerView: View {
|
||||||
)
|
)
|
||||||
.tag(index)
|
.tag(index)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
if let _ = item.detailImageUrl {
|
if let _ = item.detailImageUrl {
|
||||||
AppState.shared.setAppStep(step: .eventDetail(event: item))
|
AppState.shared.setAppStep(step: .eventDetail(event: item))
|
||||||
} else if let link = item.link, link.trimmingCharacters(in: .whitespaces).count > 0, let url = URL(string: link), UIApplication.shared.canOpenURL(url) {
|
} else if let link = item.link, link.trimmingCharacters(in: .whitespaces).count > 0, let url = URL(string: link), UIApplication.shared.canOpenURL(url) {
|
||||||
UIApplication.shared.open(url)
|
UIApplication.shared.open(url)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct LiveView: View {
|
||||||
|
|
||||||
@StateObject var viewModel = LiveViewModel()
|
@StateObject var viewModel = LiveViewModel()
|
||||||
@StateObject var appState = AppState.shared
|
@StateObject var appState = AppState.shared
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
@ -44,9 +45,13 @@ struct LiveView: View {
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .contentAllByTheme(themeId: 7)
|
step: .contentAllByTheme(themeId: 7)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if viewModel.recommendChannelItems.count > 0 {
|
if viewModel.recommendChannelItems.count > 0 {
|
||||||
|
@ -61,10 +66,18 @@ struct LiveView: View {
|
||||||
SectionLiveNowView(
|
SectionLiveNowView(
|
||||||
items: viewModel.liveNowItems,
|
items: viewModel.liveNowItems,
|
||||||
onClickParticipant: {
|
onClickParticipant: {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
viewModel.enterLiveRoom(roomId: $0)
|
viewModel.enterLiveRoom(roomId: $0)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onTapCreateLive: {
|
onTapCreateLive: {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onClickRefresh: {
|
onClickRefresh: {
|
||||||
viewModel.getSummary()
|
viewModel.getSummary()
|
||||||
|
@ -82,12 +95,26 @@ struct LiveView: View {
|
||||||
SectionLiveReservationView(
|
SectionLiveReservationView(
|
||||||
items: viewModel.liveReservationItems,
|
items: viewModel.liveReservationItems,
|
||||||
onClickCancel: { viewModel.getSummary() },
|
onClickCancel: { viewModel.getSummary() },
|
||||||
onClickStart: { roomId in processStart(roomId: roomId) },
|
onClickStart: { roomId in
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
processStart(roomId: roomId)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
|
},
|
||||||
onClickReservation: { roomId in
|
onClickReservation: { roomId in
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
viewModel.reservationLiveRoom(roomId: roomId)
|
viewModel.reservationLiveRoom(roomId: roomId)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onTapCreateLive: {
|
onTapCreateLive: {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .RESERVATION, onSuccess: onCreateSuccess))
|
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .RESERVATION, onSuccess: onCreateSuccess))
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -102,7 +129,11 @@ struct LiveView: View {
|
||||||
.padding(.trailing, 16)
|
.padding(.trailing, 16)
|
||||||
.padding(.bottom, 16)
|
.padding(.bottom, 16)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,17 @@ final class LiveViewModel: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSummary() {
|
func getSummary() {
|
||||||
|
if !UserDefaults.string(forKey: UserDefaultsKey.token).trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
getFollowedChannelList()
|
getFollowedChannelList()
|
||||||
|
}
|
||||||
|
|
||||||
getRecommendChannelList()
|
getRecommendChannelList()
|
||||||
getRecommendLive()
|
getRecommendLive()
|
||||||
|
|
||||||
|
if !UserDefaults.string(forKey: UserDefaultsKey.token).trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
getLatestPostListFromCreatorsYouFollow()
|
getLatestPostListFromCreatorsYouFollow()
|
||||||
|
}
|
||||||
|
|
||||||
isLoading = true
|
isLoading = true
|
||||||
|
|
||||||
eventBannerItems.removeAll()
|
eventBannerItems.removeAll()
|
||||||
|
|
|
@ -15,6 +15,8 @@ struct SectionLiveNowView: View {
|
||||||
let onTapCreateLive: () -> Void
|
let onTapCreateLive: () -> Void
|
||||||
let onClickRefresh: () -> Void
|
let onClickRefresh: () -> Void
|
||||||
|
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
LazyVStack(spacing: 13.3) {
|
LazyVStack(spacing: 13.3) {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
|
@ -45,6 +47,7 @@ struct SectionLiveNowView: View {
|
||||||
LiveNowItemView(item: item)
|
LiveNowItemView(item: item)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .liveDetail(
|
step: .liveDetail(
|
||||||
roomId: item.roomId,
|
roomId: item.roomId,
|
||||||
|
@ -59,6 +62,9 @@ struct SectionLiveNowView: View {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ struct SectionRecommendLiveView: View {
|
||||||
let items: [GetRecommendLiveResponse]
|
let items: [GetRecommendLiveResponse]
|
||||||
@State private var currentIndex = 0
|
@State private var currentIndex = 0
|
||||||
@State private var timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
|
@State private var timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
|
@ -27,11 +28,13 @@ struct SectionRecommendLiveView: View {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
Image("ic_message")
|
Image("ic_message")
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState.shared.setAppStep(step: .message)
|
AppState.shared.setAppStep(step: .message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
||||||
|
|
||||||
TabView(selection: $currentIndex) {
|
TabView(selection: $currentIndex) {
|
||||||
|
@ -53,7 +56,11 @@ struct SectionRecommendLiveView: View {
|
||||||
height: (screenSize().width - 26.7) * 0.53
|
height: (screenSize().width - 26.7) * 0.53
|
||||||
)
|
)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cornerRadius(4.7)
|
.cornerRadius(4.7)
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,7 +79,11 @@ struct SectionRecommendLiveView: View {
|
||||||
height: (screenSize().width - 26.7) * 0.53
|
height: (screenSize().width - 26.7) * 0.53
|
||||||
)
|
)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cornerRadius(4.7)
|
.cornerRadius(4.7)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ struct SectionRecommendChannelView: View {
|
||||||
let items: [GetRecommendChannelResponse]
|
let items: [GetRecommendChannelResponse]
|
||||||
|
|
||||||
@Binding var isFollowingList: Bool
|
@Binding var isFollowingList: Bool
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 21.3) {
|
VStack(spacing: 21.3) {
|
||||||
|
@ -20,22 +21,23 @@ struct SectionRecommendChannelView: View {
|
||||||
if isFollowingList {
|
if isFollowingList {
|
||||||
Text("팔로잉 ")
|
Text("팔로잉 ")
|
||||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
.foregroundColor(Color(hex: "eeeeee"))
|
.foregroundColor(.grayee)
|
||||||
} else {
|
} else {
|
||||||
Text("추천 ")
|
Text("추천 ")
|
||||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
.foregroundColor(Color(hex: "eeeeee"))
|
.foregroundColor(.grayee)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text("채널")
|
Text("채널")
|
||||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
.foregroundColor(Color(hex: "3bb9f1"))
|
.foregroundColor(.button)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
Text("팔로잉 채널")
|
Text("팔로잉 채널")
|
||||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||||
.foregroundColor(Color(hex: "777777"))
|
.foregroundColor(.gray77)
|
||||||
|
|
||||||
Image(isFollowingList ? "btn_toggle_on_big" : "btn_toggle_off_big")
|
Image(isFollowingList ? "btn_toggle_on_big" : "btn_toggle_off_big")
|
||||||
.resizable()
|
.resizable()
|
||||||
|
@ -45,6 +47,7 @@ struct SectionRecommendChannelView: View {
|
||||||
isFollowingList.toggle()
|
isFollowingList.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
||||||
|
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
|
@ -70,7 +73,7 @@ struct SectionRecommendChannelView: View {
|
||||||
Circle()
|
Circle()
|
||||||
.strokeBorder(lineWidth: 3)
|
.strokeBorder(lineWidth: 3)
|
||||||
.foregroundColor(
|
.foregroundColor(
|
||||||
Color(hex: "3bb9f1")
|
.button
|
||||||
.opacity(item.isOnAir ? 1 : 0)
|
.opacity(item.isOnAir ? 1 : 0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -81,21 +84,25 @@ struct SectionRecommendChannelView: View {
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
.padding(.vertical, 2.7)
|
.padding(.vertical, 2.7)
|
||||||
.padding(.horizontal, 5.7)
|
.padding(.horizontal, 5.7)
|
||||||
.background(Color(hex: "3bb9f1"))
|
.background(Color.button)
|
||||||
.cornerRadius(6.7)
|
.cornerRadius(6.7)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(item.nickname)
|
Text(item.nickname)
|
||||||
.font(.custom(Font.medium.rawValue, size: 11.3))
|
.font(.custom(Font.medium.rawValue, size: 11.3))
|
||||||
.foregroundColor(Color(hex: "bbbbbb"))
|
.foregroundColor(Color.graybb)
|
||||||
.frame(width: screenSize().width * 0.18)
|
.frame(width: screenSize().width * 0.18)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .creatorDetail(userId: item.creatorId)
|
step: .creatorDetail(userId: item.creatorId)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +119,16 @@ struct SectionRecommendChannelView: View {
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(step: .followingList)
|
AppState.shared.setAppStep(step: .followingList)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct SectionLiveReservationView: View {
|
||||||
let onClickStart: (Int) -> Void
|
let onClickStart: (Int) -> Void
|
||||||
let onClickReservation: (Int) -> Void
|
let onClickReservation: (Int) -> Void
|
||||||
let onTapCreateLive: () -> Void
|
let onTapCreateLive: () -> Void
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 13.3) {
|
VStack(spacing: 13.3) {
|
||||||
|
@ -34,6 +35,7 @@ struct SectionLiveReservationView: View {
|
||||||
.font(.custom(Font.light.rawValue, size: 11.3))
|
.font(.custom(Font.light.rawValue, size: 11.3))
|
||||||
.foregroundColor(Color(hex: "bbbbbb"))
|
.foregroundColor(Color(hex: "bbbbbb"))
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .liveReservationAll(
|
step: .liveReservationAll(
|
||||||
onClickReservation: onClickReservation,
|
onClickReservation: onClickReservation,
|
||||||
|
@ -42,6 +44,9 @@ struct SectionLiveReservationView: View {
|
||||||
onTapCreateLive: onTapCreateLive
|
onTapCreateLive: onTapCreateLive
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +62,7 @@ struct SectionLiveReservationView: View {
|
||||||
MyLiveReservationItemView(item: item, index: index)
|
MyLiveReservationItemView(item: item, index: index)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .liveDetail(
|
step: .liveDetail(
|
||||||
roomId: item.roomId,
|
roomId: item.roomId,
|
||||||
|
@ -66,11 +72,15 @@ struct SectionLiveReservationView: View {
|
||||||
onClickCancel: onClickCancel
|
onClickCancel: onClickCancel
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LiveReservationItemView(item: item)
|
LiveReservationItemView(item: item)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared.setAppStep(
|
AppState.shared.setAppStep(
|
||||||
step: .liveDetail(
|
step: .liveDetail(
|
||||||
roomId: item.roomId,
|
roomId: item.roomId,
|
||||||
|
@ -80,6 +90,9 @@ struct SectionLiveReservationView: View {
|
||||||
onClickCancel: onClickCancel
|
onClickCancel: onClickCancel
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
AppState.shared.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct HomeView: View {
|
||||||
private let contentView = ContentMainTabHomeView()
|
private let contentView = ContentMainTabHomeView()
|
||||||
|
|
||||||
@State private var isShowPlayer = false
|
@State private var isShowPlayer = false
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { proxy in
|
GeometryReader { proxy in
|
||||||
|
@ -168,11 +169,13 @@ struct HomeView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
pushTokenUpdate()
|
pushTokenUpdate()
|
||||||
viewModel.getMemberInfo()
|
viewModel.getMemberInfo()
|
||||||
viewModel.getEventPopup()
|
viewModel.getEventPopup()
|
||||||
viewModel.addAllPlaybackTracking()
|
viewModel.addAllPlaybackTracking()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if appState.isShowPlayer {
|
if appState.isShowPlayer {
|
||||||
LiveRoomViewV2()
|
LiveRoomViewV2()
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
//
|
|
||||||
// MainView.swift
|
|
||||||
// SodaLive
|
|
||||||
//
|
|
||||||
// Created by klaus on 2023/08/09.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct MainView: View {
|
|
||||||
|
|
||||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
if token.count > 0 {
|
|
||||||
HomeView()
|
|
||||||
} else {
|
|
||||||
LoginView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MainView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
MainView()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,10 +17,12 @@ struct MyPageView: View {
|
||||||
@StateObject var viewModel = MyPageViewModel()
|
@StateObject var viewModel = MyPageViewModel()
|
||||||
|
|
||||||
@State private var payload = Payload()
|
@State private var payload = Payload()
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BaseView(isLoading: $viewModel.isLoading) {
|
BaseView(isLoading: $viewModel.isLoading) {
|
||||||
if viewModel.isShowAuthView {
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||||
|
viewModel.isShowAuthView {
|
||||||
BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION)
|
BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION)
|
||||||
.onConfirm {
|
.onConfirm {
|
||||||
DEBUG_LOG("onConfirm: \($0)")
|
DEBUG_LOG("onConfirm: \($0)")
|
||||||
|
@ -47,6 +49,7 @@ struct MyPageView: View {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
VStack {
|
VStack {
|
||||||
HomeNavigationBar(title: "마이 페이지") {
|
HomeNavigationBar(title: "마이 페이지") {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
Image("ic_settings")
|
Image("ic_settings")
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
|
@ -54,6 +57,8 @@ struct MyPageView: View {
|
||||||
AppState.shared.setAppStep(step: .settings)
|
AppState.shared.setAppStep(step: .settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
RefreshableScrollView(
|
RefreshableScrollView(
|
||||||
refreshing: $viewModel.isLoading,
|
refreshing: $viewModel.isLoading,
|
||||||
action: {
|
action: {
|
||||||
|
@ -206,14 +211,106 @@ struct MyPageView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
|
VStack(spacing: 24) {
|
||||||
|
HStack(spacing: 6.7) {
|
||||||
|
Image("ic_logo_circle_gray")
|
||||||
|
|
||||||
|
Text("Login")
|
||||||
|
.font(.custom(Font.medium.rawValue, size: 32))
|
||||||
|
.foregroundColor(.gray90)
|
||||||
|
}
|
||||||
|
.padding(20)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.background(Color.bg)
|
||||||
|
.cornerRadius(6.7)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
.padding(.top, 24)
|
||||||
|
.onTapGesture {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
HStack(spacing: 6.7) {
|
||||||
|
Text("0")
|
||||||
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
|
.foregroundColor(.grayee)
|
||||||
|
|
||||||
|
Image("ic_can")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
|
||||||
|
Image("ic_forward")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack(spacing: 7) {
|
||||||
|
Image("ic_coin_w")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 26.7, height: 26.7)
|
||||||
|
|
||||||
|
Text("충전")
|
||||||
|
.font(.custom(Font.bold.rawValue, size: 12))
|
||||||
|
.foregroundColor(Color(hex: "b38fff"))
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 11.3)
|
||||||
|
.padding(.vertical, 7)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: CGFloat(16.7))
|
||||||
|
.stroke(lineWidth: 1)
|
||||||
|
.foregroundColor(Color(hex: "b38fff"))
|
||||||
|
)
|
||||||
|
.cornerRadius(16.7)
|
||||||
|
.onTapGesture {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
.background(Color.gray22)
|
||||||
|
.cornerRadius(6.7)
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
|
||||||
|
ServiceCenterButtonView()
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
|
||||||
|
if let url = URL(string: "https://blog.naver.com/sodalive_official"),
|
||||||
|
UIApplication.shared.canOpenURL(url) {
|
||||||
|
Image("img_how_to_use")
|
||||||
|
.resizable()
|
||||||
|
.frame(
|
||||||
|
width: screenSize().width,
|
||||||
|
height: (200 * screenSize().width) / 1080
|
||||||
|
)
|
||||||
|
.onTapGesture {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.frame(width: geo.size.width, height: geo.size.height)
|
.frame(width: geo.size.width, height: geo.size.height)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
viewModel.getMypage()
|
viewModel.getMypage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) {
|
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
HStack {
|
HStack {
|
||||||
|
|
|
@ -43,6 +43,6 @@ extension FaqApi: TargetType {
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers: [String : String]? {
|
var headers: [String : String]? {
|
||||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,9 @@ struct ServiceCenterButtonView: View {
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
.frame(width: screenSize().width - 26.7, height: 66.7)
|
.frame(height: 66.7)
|
||||||
.background(Color(hex: "13181b"))
|
.frame(maxWidth: .infinity)
|
||||||
|
.background(Color.bg)
|
||||||
.cornerRadius(6.7)
|
.cornerRadius(6.7)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
AppState.shared.setAppStep(step: .serviceCenter)
|
AppState.shared.setAppStep(step: .serviceCenter)
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct ServiceCenterView: View {
|
||||||
|
|
||||||
Text("고객센터")
|
Text("고객센터")
|
||||||
.font(.custom(Font.bold.rawValue, size: 20))
|
.font(.custom(Font.bold.rawValue, size: 20))
|
||||||
.foregroundColor(Color(hex: "eeeeee"))
|
.foregroundColor(.grayee)
|
||||||
|
|
||||||
HStack(spacing: 13.3) {
|
HStack(spacing: 13.3) {
|
||||||
Image("ic_service_center_kakao")
|
Image("ic_service_center_kakao")
|
||||||
|
@ -48,13 +48,14 @@ struct ServiceCenterView: View {
|
||||||
|
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.frame(width: screenSize().width, height: 6.7)
|
.frame(width: screenSize().width, height: 6.7)
|
||||||
.foregroundColor(Color(hex: "232323"))
|
.foregroundColor(.gray23)
|
||||||
.padding(.vertical, 20)
|
.padding(.vertical, 20)
|
||||||
|
|
||||||
Text("자주 묻는 질문")
|
Text("자주 묻는 질문")
|
||||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
.foregroundColor(Color(hex: "eeeeee"))
|
.foregroundColor(.grayee)
|
||||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding(.horizontal, 13.3)
|
||||||
|
|
||||||
ServiceCenterCategoryView(
|
ServiceCenterCategoryView(
|
||||||
categories: viewModel.categories,
|
categories: viewModel.categories,
|
||||||
|
|
|
@ -20,6 +20,9 @@ struct SettingsView: View {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
DetailNavigationBar(title: "설정")
|
DetailNavigationBar(title: "설정")
|
||||||
|
|
||||||
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
|
VStack(spacing: 0) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Text("공지사항")
|
Text("공지사항")
|
||||||
|
@ -198,8 +201,6 @@ struct SettingsView: View {
|
||||||
.frame(width: cardWidth, alignment: .leading)
|
.frame(width: cardWidth, alignment: .leading)
|
||||||
.padding(.top, 13.3)
|
.padding(.top, 13.3)
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Text("로그아웃")
|
Text("로그아웃")
|
||||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.grayee)
|
.foregroundColor(Color.grayee)
|
||||||
|
@ -209,6 +210,7 @@ struct SettingsView: View {
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
isShowLogoutDialog = true
|
isShowLogoutDialog = true
|
||||||
}
|
}
|
||||||
|
.padding(.top, 46.7)
|
||||||
|
|
||||||
Text("모든 기기에서 로그아웃")
|
Text("모든 기기에서 로그아웃")
|
||||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||||
|
@ -228,6 +230,8 @@ struct SettingsView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if isShowLogoutDialog {
|
if isShowLogoutDialog {
|
||||||
SodaDialog(
|
SodaDialog(
|
||||||
|
@ -239,8 +243,9 @@ struct SettingsView: View {
|
||||||
ContentPlayerPlayManager.shared.resetPlayer()
|
ContentPlayerPlayManager.shared.resetPlayer()
|
||||||
viewModel.logout {
|
viewModel.logout {
|
||||||
self.isShowLogoutDialog = false
|
self.isShowLogoutDialog = false
|
||||||
AppState.shared.setAppStep(step: .main)
|
|
||||||
UserDefaults.reset()
|
UserDefaults.reset()
|
||||||
|
AppState.shared.isChangeAdultContentVisible = true
|
||||||
|
AppState.shared.setAppStep(step: .splash)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cancelButtonTitle: "취소",
|
cancelButtonTitle: "취소",
|
||||||
|
@ -260,8 +265,9 @@ struct SettingsView: View {
|
||||||
ContentPlayerPlayManager.shared.resetPlayer()
|
ContentPlayerPlayManager.shared.resetPlayer()
|
||||||
viewModel.logoutAllDevice {
|
viewModel.logoutAllDevice {
|
||||||
self.isShowLogoutAllDeviceDialog = false
|
self.isShowLogoutAllDeviceDialog = false
|
||||||
AppState.shared.setAppStep(step: .main)
|
|
||||||
UserDefaults.reset()
|
UserDefaults.reset()
|
||||||
|
AppState.shared.isChangeAdultContentVisible = true
|
||||||
|
AppState.shared.setAppStep(step: .splash)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cancelButtonTitle: "취소",
|
cancelButtonTitle: "취소",
|
||||||
|
|
|
@ -56,6 +56,7 @@ final class SignOutViewModel: ObservableObject {
|
||||||
|
|
||||||
if decoded.success {
|
if decoded.success {
|
||||||
UserDefaults.reset()
|
UserDefaults.reset()
|
||||||
|
AppState.shared.isChangeAdultContentVisible = true
|
||||||
AppState.shared.setAppStep(step: .splash)
|
AppState.shared.setAppStep(step: .splash)
|
||||||
} else {
|
} else {
|
||||||
if let message = decoded.message {
|
if let message = decoded.message {
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Kingfisher
|
||||||
|
|
||||||
struct SeriesListBigItemView: View {
|
struct SeriesListBigItemView: View {
|
||||||
|
|
||||||
|
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||||
|
|
||||||
let item: SeriesListItem
|
let item: SeriesListItem
|
||||||
let isVisibleCreator: Bool
|
let isVisibleCreator: Bool
|
||||||
|
|
||||||
|
@ -26,8 +28,13 @@ struct SeriesListBigItemView: View {
|
||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
.clipped()
|
.clipped()
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared
|
AppState.shared
|
||||||
.setAppStep(step: .seriesDetail(seriesId: item.seriesId))
|
.setAppStep(step: .seriesDetail(seriesId: item.seriesId))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
|
@ -80,8 +87,13 @@ struct SeriesListBigItemView: View {
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
|
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
AppState.shared
|
AppState.shared
|
||||||
.setAppStep(step: .creatorDetail(userId: item.creator.creatorId))
|
.setAppStep(step: .creatorDetail(userId: item.creator.creatorId))
|
||||||
|
} else {
|
||||||
|
AppState.shared
|
||||||
|
.setAppStep(step: .login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct LoginView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BaseView(isLoading: $viewModel.isLoading) {
|
BaseView(isLoading: $viewModel.isLoading) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
HomeNavigationBar(title: "로그인") {}
|
DetailNavigationBar(title: "로그인")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ final class LoginViewModel: ObservableObject {
|
||||||
UserDefaults.set(data.userId, forKey: .userId)
|
UserDefaults.set(data.userId, forKey: .userId)
|
||||||
UserDefaults.set(data.email, forKey: .email)
|
UserDefaults.set(data.email, forKey: .email)
|
||||||
UserDefaults.set(data.token, forKey: .token)
|
UserDefaults.set(data.token, forKey: .token)
|
||||||
|
AppState.shared.isChangeAdultContentVisible = true
|
||||||
|
AppState.shared.setAppStep(step: .splash)
|
||||||
} else {
|
} else {
|
||||||
if let message = decoded.message {
|
if let message = decoded.message {
|
||||||
self.errorMessage = message
|
self.errorMessage = message
|
||||||
|
|
|
@ -58,7 +58,8 @@ final class SignUpViewModel: ObservableObject {
|
||||||
UserDefaults.set(data.userId, forKey: .userId)
|
UserDefaults.set(data.userId, forKey: .userId)
|
||||||
UserDefaults.set(data.email, forKey: .email)
|
UserDefaults.set(data.email, forKey: .email)
|
||||||
UserDefaults.set(data.token, forKey: .token)
|
UserDefaults.set(data.token, forKey: .token)
|
||||||
AppState.shared.back()
|
AppState.shared.isChangeAdultContentVisible = true
|
||||||
|
AppState.shared.setAppStep(step: .splash)
|
||||||
} else {
|
} else {
|
||||||
if let message = decoded.message {
|
if let message = decoded.message {
|
||||||
self.errorMessage = message
|
self.errorMessage = message
|
||||||
|
|
Loading…
Reference in New Issue