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 login
|
||||
|
||||
case signUp
|
||||
|
||||
case findPassword
|
||||
|
|
|
@ -89,6 +89,12 @@ extension AuditionApi: TargetType {
|
|||
}
|
||||
|
||||
var headers: [String : String]? {
|
||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
||||
switch self {
|
||||
case .getAuditionList:
|
||||
return nil
|
||||
|
||||
default:
|
||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,15 +11,18 @@ struct AuditionView: View {
|
|||
|
||||
@StateObject var viewModel = AuditionViewModel()
|
||||
@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 {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
HomeNavigationBar(title: "오디션") {
|
||||
Image(isAuditionNotification ? "btn_audition_notification_selected" : "btn_audition_notification_normal")
|
||||
.onTapGesture {
|
||||
viewModel.updateNotificationSettings()
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
Image(isAuditionNotification ? "btn_audition_notification_selected" : "btn_audition_notification_normal")
|
||||
.onTapGesture {
|
||||
viewModel.updateNotificationSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
|
@ -70,11 +73,16 @@ struct AuditionView: View {
|
|||
|
||||
AuditionItemView(item: item)
|
||||
.onTapGesture {
|
||||
if !item.isOff {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if !item.isOff {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .auditionDetail(auditionId: item.id)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .auditionDetail(auditionId: item.id)
|
||||
)
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,23 +112,20 @@ struct AuditionView: View {
|
|||
|
||||
AuditionItemView(item: item)
|
||||
.padding(.top, 25)
|
||||
.onTapGesture {
|
||||
}
|
||||
} else {
|
||||
AuditionItemView(item: item)
|
||||
.onTapGesture {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if !item.isOff {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .auditionDetail(auditionId: item.id)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AuditionItemView(item: item)
|
||||
.onTapGesture {
|
||||
if !item.isOff {
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .auditionDetail(auditionId: item.id)
|
||||
)
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ enum ContentApi {
|
|||
|
||||
case getContentMainHome(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 getRecommendSeriesListByGenre(genreId: Int, isAdultContentVisible: Bool, contentType: ContentType)
|
||||
|
@ -168,6 +169,9 @@ extension ContentApi: TargetType {
|
|||
case .getPopularContentByCreator:
|
||||
return "/v2/audio-content/main/home/popular-content-by-creator"
|
||||
|
||||
case .getContentMainHomeContentRanking:
|
||||
return "/v2/audio-content/main/home/content/ranking"
|
||||
|
||||
case .getContentMainSeries:
|
||||
return "/v2/audio-content/main/series"
|
||||
|
||||
|
@ -238,7 +242,7 @@ extension ContentApi: TargetType {
|
|||
case .getMainBannerList, .getMainOrderList, .getNewContentUploadCreatorList, .getCurationList, .getAudioContentByTheme:
|
||||
return .get
|
||||
|
||||
case .getContentMainHome, .getPopularContentByCreator, .getContentMainSeries, .getRecommendSeriesListByGenre, .getRecommendSeriesByCreator, .getContentMainContent,
|
||||
case .getContentMainHome, .getPopularContentByCreator, .getContentMainHomeContentRanking, .getContentMainSeries, .getRecommendSeriesListByGenre, .getRecommendSeriesByCreator, .getContentMainContent,
|
||||
.getContentMainNewContentOfTheme, .getDailyContentRanking, .getRecommendContentByTag, .getContentMainAlarm, .getContentMainAlarmAll,
|
||||
.getContentMainAsmr, .getPopularAsmrContentByCreator, .getContentMainReplay, .getPopularReplayContentByCreator,
|
||||
.getContentMainFree, .getIntroduceCreatorList, .getNewFreeContentOfTheme, .getPopularFreeContentByCreator, .getCompletedSeries, .getContentMainContentPopularContentByCreator:
|
||||
|
@ -439,6 +443,15 @@ extension ContentApi: TargetType {
|
|||
|
||||
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):
|
||||
let parameters = [
|
||||
"creatorId": creatorId,
|
||||
|
|
|
@ -11,6 +11,8 @@ import Kingfisher
|
|||
|
||||
struct ContentMainTabRankContentView: View {
|
||||
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
let rows = [
|
||||
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)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState
|
||||
.shared
|
||||
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import Kingfisher
|
|||
|
||||
struct ContentByChannelView: View {
|
||||
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
let title: String
|
||||
let creatorList: [ContentCreatorResponse]
|
||||
let contentList: [GetAudioContentRankingItem]
|
||||
|
@ -111,15 +113,23 @@ struct ContentByChannelView: View {
|
|||
.foregroundColor(.gray77)
|
||||
}
|
||||
.onTapGesture {
|
||||
AppState
|
||||
.shared
|
||||
.setAppStep(step: .creatorDetail(userId: content.creatorId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.setAppStep(step: .creatorDetail(userId: content.creatorId))
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
AppState
|
||||
.shared
|
||||
.setAppStep(step: .contentDetail(contentId: content.contentId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.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 {
|
||||
|
||||
@StateObject var viewModel = ContentMainTabHomeViewModel()
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
|
@ -29,10 +30,12 @@ struct ContentMainTabHomeView: View {
|
|||
|
||||
Spacer()
|
||||
|
||||
Image("ic_content_keep")
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
Image("ic_content_keep")
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
|
@ -45,153 +48,156 @@ struct ContentMainTabHomeView: View {
|
|||
.padding(.horizontal, 13.3)
|
||||
}
|
||||
|
||||
if viewModel.bannerList.count > 0 {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||
viewModel.bannerList.count > 0 {
|
||||
ContentMainBannerViewV2(bannerList: viewModel.bannerList)
|
||||
.padding(.top, 30)
|
||||
.padding(.horizontal, 13.3)
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image("ic_title_search_black")
|
||||
|
||||
Text("채널명을 입력해 보세요")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color.gray55)
|
||||
.keyboardType(.default)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal, 21.3)
|
||||
.frame(height: 50)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.gray22)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color.graybb)
|
||||
)
|
||||
.padding(.top, 30)
|
||||
.padding(.horizontal, 13.3)
|
||||
.onTapGesture {
|
||||
UserDefaults.set("", forKey: .searchChannel)
|
||||
AppState.shared.setAppStep(step: .searchChannel)
|
||||
}
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
HStack(spacing: 0) {
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_series",
|
||||
title: "시리즈",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .SERIES
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
Image("ic_title_search_black")
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_content",
|
||||
title: "단편",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .CONTENT
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
Text("채널명을 입력해 보세요")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color.gray55)
|
||||
.keyboardType(.default)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_alarm",
|
||||
title: "모닝콜",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .ALARM
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_asmr",
|
||||
title: "ASMR",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .ASMR
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal, 21.3)
|
||||
.frame(height: 50)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.gray22)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.strokeBorder(lineWidth: 1)
|
||||
.foregroundColor(Color.graybb)
|
||||
)
|
||||
.padding(.top, 30)
|
||||
.padding(.horizontal, 13.3)
|
||||
.onTapGesture {
|
||||
UserDefaults.set("", forKey: .searchChannel)
|
||||
AppState.shared.setAppStep(step: .searchChannel)
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_replay",
|
||||
title: "다시듣기",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .REPLAY
|
||||
VStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_series",
|
||||
title: "시리즈",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .SERIES
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_free",
|
||||
title: "무료",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .FREE
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_content",
|
||||
title: "단편",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .CONTENT
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_alarm",
|
||||
title: "모닝콜",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .ALARM
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_asmr",
|
||||
title: "ASMR",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .ASMR
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_audio_book",
|
||||
title: "오디오북",
|
||||
onClick: {
|
||||
viewModel.errorMessage = "준비중입니다."
|
||||
viewModel.isShowPopup = true
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_audio_toon",
|
||||
title: "오디오툰",
|
||||
onClick: {
|
||||
viewModel.errorMessage = "준비중입니다."
|
||||
viewModel.isShowPopup = true
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
HStack(spacing: 0) {
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_replay",
|
||||
title: "다시듣기",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .REPLAY
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_free",
|
||||
title: "무료",
|
||||
onClick: {
|
||||
AppState.shared
|
||||
.setAppStep(
|
||||
step: .contentMain(
|
||||
startTab: .FREE
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_audio_book",
|
||||
title: "오디오북",
|
||||
onClick: {
|
||||
viewModel.errorMessage = "준비중입니다."
|
||||
viewModel.isShowPopup = true
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
ContentMainTabCategoryView(
|
||||
imageName: "ic_category_audio_toon",
|
||||
title: "오디오툰",
|
||||
onClick: {
|
||||
viewModel.errorMessage = "준비중입니다."
|
||||
viewModel.isShowPopup = true
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(5.3)
|
||||
.padding(.top, 30)
|
||||
.padding(.horizontal, 13.3)
|
||||
}
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(5.3)
|
||||
.padding(.top, 30)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
if let response = viewModel.rankCreatorResponse {
|
||||
ContentMainTabHomeRankCreatorView(response: response)
|
||||
|
@ -210,7 +216,11 @@ struct ContentMainTabHomeView: View {
|
|||
title: "인기 단편",
|
||||
isMore: true,
|
||||
onClickMore: {
|
||||
AppState.shared.setAppStep(step: .contentRankingAll)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(step: .contentRankingAll)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
},
|
||||
sortList: !viewModel.rankSortTypeList.isEmpty ?
|
||||
viewModel.rankSortTypeList :
|
||||
|
@ -221,7 +231,8 @@ struct ContentMainTabHomeView: View {
|
|||
.padding(.top, 30)
|
||||
}
|
||||
|
||||
if viewModel.eventBannerList.count > 0 {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||
viewModel.eventBannerList.count > 0 {
|
||||
SectionEventBannerView(items: viewModel.eventBannerList)
|
||||
.padding(.top, 30)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import Combine
|
|||
final class ContentMainTabHomeViewModel: ObservableObject {
|
||||
|
||||
private let repository = ContentMainTabHomeRepository()
|
||||
private let contentRepository = ContentRepository()
|
||||
private var subscription = Set<AnyCancellable>()
|
||||
|
||||
@Published var errorMessage = ""
|
||||
|
@ -77,7 +76,7 @@ final class ContentMainTabHomeViewModel: ObservableObject {
|
|||
|
||||
func getContentRanking(sort: String = "매출") {
|
||||
isLoading = true
|
||||
contentRepository.getContentRanking(page: 1, size: 12, sortType: sort)
|
||||
repository.getContentRanking(sortType: sort)
|
||||
.sink { result in
|
||||
switch result {
|
||||
case .finished:
|
||||
|
@ -90,10 +89,10 @@ final class ContentMainTabHomeViewModel: ObservableObject {
|
|||
|
||||
do {
|
||||
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 {
|
||||
self.rankContentList = data.items
|
||||
self.rankContentList = data
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
|
|
|
@ -10,6 +10,8 @@ import Kingfisher
|
|||
|
||||
struct ContentMainTabHomeRankCreatorView: View {
|
||||
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
let response: GetExplorerSectionResponse
|
||||
|
||||
let rankingCrawns = ["ic_crown_1", "ic_crown_2", "ic_crown_3"]
|
||||
|
@ -121,8 +123,13 @@ struct ContentMainTabHomeRankCreatorView: View {
|
|||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared
|
||||
.setAppStep(step: .creatorDetail(userId: creator.id))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.setAppStep(step: .creatorDetail(userId: creator.id))
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,16 @@ struct ContentView: View {
|
|||
if appState.isChangeAdultContentVisible {
|
||||
EmptyView()
|
||||
} else {
|
||||
MainView()
|
||||
HomeView()
|
||||
}
|
||||
|
||||
switch appState.appStep {
|
||||
case .splash:
|
||||
SplashView()
|
||||
|
||||
case .login:
|
||||
LoginView()
|
||||
|
||||
case .signUp:
|
||||
SignUpView()
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ struct SectionEventBannerView: View {
|
|||
|
||||
@State private var currentIndex = 0
|
||||
@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]
|
||||
|
||||
|
@ -38,10 +39,14 @@ struct SectionEventBannerView: View {
|
|||
)
|
||||
.tag(index)
|
||||
.onTapGesture {
|
||||
if let _ = item.detailImageUrl {
|
||||
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) {
|
||||
UIApplication.shared.open(url)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if let _ = item.detailImageUrl {
|
||||
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) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -62,10 +67,14 @@ struct SectionEventBannerView: View {
|
|||
)
|
||||
.tag(index)
|
||||
.onTapGesture {
|
||||
if let _ = item.detailImageUrl {
|
||||
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) {
|
||||
UIApplication.shared.open(url)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if let _ = item.detailImageUrl {
|
||||
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) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ struct LiveView: View {
|
|||
|
||||
@StateObject var viewModel = LiveViewModel()
|
||||
@StateObject var appState = AppState.shared
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
|
@ -44,9 +45,13 @@ struct LiveView: View {
|
|||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .contentAllByTheme(themeId: 7)
|
||||
)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .contentAllByTheme(themeId: 7)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
|
||||
if viewModel.recommendChannelItems.count > 0 {
|
||||
|
@ -61,10 +66,18 @@ struct LiveView: View {
|
|||
SectionLiveNowView(
|
||||
items: viewModel.liveNowItems,
|
||||
onClickParticipant: {
|
||||
viewModel.enterLiveRoom(roomId: $0)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
viewModel.enterLiveRoom(roomId: $0)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
},
|
||||
onTapCreateLive: {
|
||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
},
|
||||
onClickRefresh: {
|
||||
viewModel.getSummary()
|
||||
|
@ -82,12 +95,26 @@ struct LiveView: View {
|
|||
SectionLiveReservationView(
|
||||
items: viewModel.liveReservationItems,
|
||||
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
|
||||
viewModel.reservationLiveRoom(roomId: roomId)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
viewModel.reservationLiveRoom(roomId: roomId)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
},
|
||||
onTapCreateLive: {
|
||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .RESERVATION, onSuccess: onCreateSuccess))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
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(.bottom, 16)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
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() {
|
||||
getFollowedChannelList()
|
||||
if !UserDefaults.string(forKey: UserDefaultsKey.token).trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
getFollowedChannelList()
|
||||
}
|
||||
|
||||
getRecommendChannelList()
|
||||
getRecommendLive()
|
||||
getLatestPostListFromCreatorsYouFollow()
|
||||
|
||||
if !UserDefaults.string(forKey: UserDefaultsKey.token).trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
getLatestPostListFromCreatorsYouFollow()
|
||||
}
|
||||
|
||||
isLoading = true
|
||||
|
||||
eventBannerItems.removeAll()
|
||||
|
|
|
@ -15,6 +15,8 @@ struct SectionLiveNowView: View {
|
|||
let onTapCreateLive: () -> Void
|
||||
let onClickRefresh: () -> Void
|
||||
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
LazyVStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
|
@ -45,20 +47,24 @@ struct SectionLiveNowView: View {
|
|||
LiveNowItemView(item: item)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {
|
||||
AppState.shared.isShowPlayer = false
|
||||
onClickParticipant(item.roomId)
|
||||
},
|
||||
onClickReservation: {},
|
||||
onClickStart: {
|
||||
},
|
||||
onClickCancel: {
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {
|
||||
AppState.shared.isShowPlayer = false
|
||||
onClickParticipant(item.roomId)
|
||||
},
|
||||
onClickReservation: {},
|
||||
onClickStart: {
|
||||
},
|
||||
onClickCancel: {
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ struct SectionRecommendLiveView: View {
|
|||
let items: [GetRecommendLiveResponse]
|
||||
@State private var currentIndex = 0
|
||||
@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 {
|
||||
VStack(spacing: 0) {
|
||||
|
@ -27,10 +28,12 @@ struct SectionRecommendLiveView: View {
|
|||
|
||||
Spacer()
|
||||
|
||||
Image("ic_message")
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .message)
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
Image("ic_message")
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .message)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
||||
|
||||
|
@ -53,7 +56,11 @@ struct SectionRecommendLiveView: View {
|
|||
height: (screenSize().width - 26.7) * 0.53
|
||||
)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
.cornerRadius(4.7)
|
||||
} else {
|
||||
|
@ -72,7 +79,11 @@ struct SectionRecommendLiveView: View {
|
|||
height: (screenSize().width - 26.7) * 0.53
|
||||
)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId))
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
.cornerRadius(4.7)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ struct SectionRecommendChannelView: View {
|
|||
let items: [GetRecommendChannelResponse]
|
||||
|
||||
@Binding var isFollowingList: Bool
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 21.3) {
|
||||
|
@ -20,30 +21,32 @@ struct SectionRecommendChannelView: View {
|
|||
if isFollowingList {
|
||||
Text("팔로잉 ")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.foregroundColor(.grayee)
|
||||
} else {
|
||||
Text("추천 ")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.foregroundColor(.grayee)
|
||||
}
|
||||
|
||||
Text("채널")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.foregroundColor(.button)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("팔로잉 채널")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color(hex: "777777"))
|
||||
|
||||
Image(isFollowingList ? "btn_toggle_on_big" : "btn_toggle_off_big")
|
||||
.resizable()
|
||||
.frame(width: 33.3, height: 20)
|
||||
.padding(.leading, 6.7)
|
||||
.onTapGesture {
|
||||
isFollowingList.toggle()
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
Text("팔로잉 채널")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(.gray77)
|
||||
|
||||
Image(isFollowingList ? "btn_toggle_on_big" : "btn_toggle_off_big")
|
||||
.resizable()
|
||||
.frame(width: 33.3, height: 20)
|
||||
.padding(.leading, 6.7)
|
||||
.onTapGesture {
|
||||
isFollowingList.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
||||
|
||||
|
@ -70,7 +73,7 @@ struct SectionRecommendChannelView: View {
|
|||
Circle()
|
||||
.strokeBorder(lineWidth: 3)
|
||||
.foregroundColor(
|
||||
Color(hex: "3bb9f1")
|
||||
.button
|
||||
.opacity(item.isOnAir ? 1 : 0)
|
||||
)
|
||||
)
|
||||
|
@ -81,21 +84,25 @@ struct SectionRecommendChannelView: View {
|
|||
.foregroundColor(.white)
|
||||
.padding(.vertical, 2.7)
|
||||
.padding(.horizontal, 5.7)
|
||||
.background(Color(hex: "3bb9f1"))
|
||||
.background(Color.button)
|
||||
.cornerRadius(6.7)
|
||||
}
|
||||
}
|
||||
|
||||
Text(item.nickname)
|
||||
.font(.custom(Font.medium.rawValue, size: 11.3))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
.foregroundColor(Color.graybb)
|
||||
.frame(width: screenSize().width * 0.18)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .creatorDetail(userId: item.creatorId)
|
||||
)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .creatorDetail(userId: item.creatorId)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,10 +119,15 @@ struct SectionRecommendChannelView: View {
|
|||
.lineLimit(1)
|
||||
}
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .followingList)
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
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 onClickReservation: (Int) -> Void
|
||||
let onTapCreateLive: () -> Void
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 13.3) {
|
||||
|
@ -34,14 +35,18 @@ struct SectionLiveReservationView: View {
|
|||
.font(.custom(Font.light.rawValue, size: 11.3))
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveReservationAll(
|
||||
onClickReservation: onClickReservation,
|
||||
onClickStart: onClickStart,
|
||||
onClickCancel: onClickCancel,
|
||||
onTapCreateLive: onTapCreateLive
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveReservationAll(
|
||||
onClickReservation: onClickReservation,
|
||||
onClickStart: onClickStart,
|
||||
onClickCancel: onClickCancel,
|
||||
onTapCreateLive: onTapCreateLive
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,29 +62,37 @@ struct SectionLiveReservationView: View {
|
|||
MyLiveReservationItemView(item: item, index: index)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {},
|
||||
onClickReservation: {},
|
||||
onClickStart: { onClickStart(item.roomId) },
|
||||
onClickCancel: onClickCancel
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {},
|
||||
onClickReservation: {},
|
||||
onClickStart: { onClickStart(item.roomId) },
|
||||
onClickCancel: onClickCancel
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LiveReservationItemView(item: item)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {},
|
||||
onClickReservation: { onClickReservation(item.roomId) },
|
||||
onClickStart: { onClickStart(item.roomId) },
|
||||
onClickCancel: onClickCancel
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared.setAppStep(
|
||||
step: .liveDetail(
|
||||
roomId: item.roomId,
|
||||
onClickParticipant: {},
|
||||
onClickReservation: { onClickReservation(item.roomId) },
|
||||
onClickStart: { onClickStart(item.roomId) },
|
||||
onClickCancel: onClickCancel
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ struct HomeView: View {
|
|||
private let contentView = ContentMainTabHomeView()
|
||||
|
||||
@State private var isShowPlayer = false
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { proxy in
|
||||
|
@ -168,10 +169,12 @@ struct HomeView: View {
|
|||
}
|
||||
}
|
||||
.onAppear {
|
||||
pushTokenUpdate()
|
||||
viewModel.getMemberInfo()
|
||||
viewModel.getEventPopup()
|
||||
viewModel.addAllPlaybackTracking()
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
pushTokenUpdate()
|
||||
viewModel.getMemberInfo()
|
||||
viewModel.getEventPopup()
|
||||
viewModel.addAllPlaybackTracking()
|
||||
}
|
||||
}
|
||||
|
||||
if appState.isShowPlayer {
|
||||
|
|
|
@ -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()
|
||||
|
||||
@State private var payload = Payload()
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
if viewModel.isShowAuthView {
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||
viewModel.isShowAuthView {
|
||||
BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION)
|
||||
.onConfirm {
|
||||
DEBUG_LOG("onConfirm: \($0)")
|
||||
|
@ -47,100 +49,45 @@ struct MyPageView: View {
|
|||
GeometryReader { geo in
|
||||
VStack {
|
||||
HomeNavigationBar(title: "마이 페이지") {
|
||||
Image("ic_settings")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .settings)
|
||||
}
|
||||
}
|
||||
RefreshableScrollView(
|
||||
refreshing: $viewModel.isLoading,
|
||||
action: {
|
||||
viewModel.getMypage()
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
Image("ic_settings")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .settings)
|
||||
}
|
||||
}
|
||||
) {
|
||||
VStack(spacing: 0) {
|
||||
if let data = viewModel.myPageResponse {
|
||||
MyInfoCardView(data: data) {
|
||||
viewModel.getMypage()
|
||||
}
|
||||
.frame(width: screenSize().width - 26.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
if UserDefaults.string(forKey: .role) == MemberRole.CREATOR.rawValue {
|
||||
Text("내 채널 보기")
|
||||
.frame(width: screenSize().width - 26.7, height: 46.7)
|
||||
.font(.custom(Font.bold.rawValue, size: 15.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
.background(Color.button)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 26.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: UserDefaults.int(forKey: .userId)))
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 10.7) {
|
||||
Text("팔로잉 리스트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(6.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.stroke(Color.button, lineWidth: 1.3)
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .followingList)
|
||||
}
|
||||
|
||||
Text("차단 리스트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(6.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.stroke(Color.button, lineWidth: 1.3)
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .blockList)
|
||||
}
|
||||
}
|
||||
.padding(.top, 26.7)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
if UserDefaults.int(forKey: .userId) != 17958 {
|
||||
CanCardView(data: data) {
|
||||
}
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
RefreshableScrollView(
|
||||
refreshing: $viewModel.isLoading,
|
||||
action: {
|
||||
viewModel.getMypage()
|
||||
}
|
||||
) {
|
||||
VStack(spacing: 0) {
|
||||
if let data = viewModel.myPageResponse {
|
||||
MyInfoCardView(data: data) {
|
||||
viewModel.getMypage()
|
||||
}
|
||||
.frame(width: screenSize().width - 26.7)
|
||||
.padding(.top, 26.7)
|
||||
}
|
||||
|
||||
if data.isAuth {
|
||||
CanChargeCouponButtonView()
|
||||
.frame(width: screenSize().width - 26.7)
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .canCoupon)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 13.3) {
|
||||
Text("내 보관함")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
if UserDefaults.string(forKey: .role) == MemberRole.CREATOR.rawValue {
|
||||
Text("내 채널 보기")
|
||||
.frame(width: screenSize().width - 26.7, height: 46.7)
|
||||
.font(.custom(Font.bold.rawValue, size: 15.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
.background(Color.button)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 26.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .creatorDetail(userId: UserDefaults.int(forKey: .userId)))
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 10.7) {
|
||||
Text("구매목록")
|
||||
Text("팔로잉 리스트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
@ -153,10 +100,10 @@ struct MyPageView: View {
|
|||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
||||
AppState.shared.setAppStep(step: .followingList)
|
||||
}
|
||||
|
||||
Text("재생목록")
|
||||
Text("차단 리스트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
@ -169,26 +116,175 @@ struct MyPageView: View {
|
|||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .playlist))
|
||||
AppState.shared.setAppStep(step: .blockList)
|
||||
}
|
||||
}
|
||||
.padding(.top, 26.7)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
if UserDefaults.int(forKey: .userId) != 17958 {
|
||||
CanCardView(data: data) {
|
||||
viewModel.getMypage()
|
||||
}
|
||||
.frame(width: screenSize().width - 26.7)
|
||||
.padding(.top, 26.7)
|
||||
}
|
||||
|
||||
if data.isAuth {
|
||||
CanChargeCouponButtonView()
|
||||
.frame(width: screenSize().width - 26.7)
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .canCoupon)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 13.3) {
|
||||
Text("내 보관함")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
HStack(spacing: 10.7) {
|
||||
Text("구매목록")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(6.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.stroke(Color.button, lineWidth: 1.3)
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .orderlist))
|
||||
}
|
||||
|
||||
Text("재생목록")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.button)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 13.3)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(6.7)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6.7)
|
||||
.stroke(Color.button, lineWidth: 1.3)
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .myBox(currentTab: .playlist))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, 33)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
ReservationStatusView(data: data)
|
||||
.padding(.top, 40)
|
||||
|
||||
ServiceCenterButtonView()
|
||||
.padding(.top, 40)
|
||||
|
||||
if !data.isAuth {
|
||||
AuthButtonView()
|
||||
.padding(.top, 40)
|
||||
.onTapGesture {
|
||||
viewModel.isShowAuthView = true
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
.padding(.vertical, 40)
|
||||
.onTapGesture {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, 33)
|
||||
}
|
||||
}
|
||||
} 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)
|
||||
|
||||
ReservationStatusView(data: data)
|
||||
.padding(.top, 40)
|
||||
|
||||
ServiceCenterButtonView()
|
||||
.padding(.top, 40)
|
||||
|
||||
if !data.isAuth {
|
||||
AuthButtonView()
|
||||
.padding(.top, 40)
|
||||
.onTapGesture {
|
||||
viewModel.isShowAuthView = true
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
if let url = URL(string: "https://blog.naver.com/sodalive_official"),
|
||||
UIApplication.shared.canOpenURL(url) {
|
||||
|
@ -198,7 +294,6 @@ struct MyPageView: View {
|
|||
width: screenSize().width,
|
||||
height: (200 * screenSize().width) / 1080
|
||||
)
|
||||
.padding(.vertical, 40)
|
||||
.onTapGesture {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
|
@ -210,7 +305,9 @@ struct MyPageView: View {
|
|||
.frame(width: geo.size.width, height: geo.size.height)
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.getMypage()
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
viewModel.getMypage()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,6 @@ extension FaqApi: TargetType {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.frame(width: screenSize().width - 26.7, height: 66.7)
|
||||
.background(Color(hex: "13181b"))
|
||||
.frame(height: 66.7)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.bg)
|
||||
.cornerRadius(6.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .serviceCenter)
|
||||
|
|
|
@ -25,7 +25,7 @@ struct ServiceCenterView: View {
|
|||
|
||||
Text("고객센터")
|
||||
.font(.custom(Font.bold.rawValue, size: 20))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.foregroundColor(.grayee)
|
||||
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_service_center_kakao")
|
||||
|
@ -48,13 +48,14 @@ struct ServiceCenterView: View {
|
|||
|
||||
Rectangle()
|
||||
.frame(width: screenSize().width, height: 6.7)
|
||||
.foregroundColor(Color(hex: "232323"))
|
||||
.foregroundColor(.gray23)
|
||||
.padding(.vertical, 20)
|
||||
|
||||
Text("자주 묻는 질문")
|
||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.frame(width: screenSize().width - 26.7, alignment: .leading)
|
||||
.foregroundColor(.grayee)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
ServiceCenterCategoryView(
|
||||
categories: viewModel.categories,
|
||||
|
|
|
@ -20,165 +20,168 @@ struct SettingsView: View {
|
|||
GeometryReader { geo in
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "설정")
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("공지사항")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .notices)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("이벤트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .events)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("알림 설정")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .notificationSettings)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.frame(width: cardWidth)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 26.7)
|
||||
|
||||
if UserDefaults.bool(forKey: .auth) {
|
||||
HStack(spacing: 0) {
|
||||
Text("콘텐츠 보기 설정")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("공지사항")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .notices)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("이벤트")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .events)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("알림 설정")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .notificationSettings)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.frame(width: cardWidth)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 26.7)
|
||||
|
||||
Spacer()
|
||||
if UserDefaults.bool(forKey: .auth) {
|
||||
HStack(spacing: 0) {
|
||||
Text("콘텐츠 보기 설정")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.contentShape(Rectangle())
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .contentViewSettings)
|
||||
}
|
||||
}
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.contentShape(Rectangle())
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .contentViewSettings)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("이용약관")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 0) {
|
||||
Text("이용약관")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .terms)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("개인정보처리방침")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .privacy)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.frame(width: cardWidth)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Spacer()
|
||||
HStack(spacing: 0) {
|
||||
Text("앱 버전 정보")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
|
||||
Text("Ver \(version!)")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .terms)
|
||||
}
|
||||
|
||||
Rectangle()
|
||||
.frame(width: cardWidth - 26.7, height: 0.3)
|
||||
.foregroundColor(Color.gray90)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("개인정보처리방침")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image("ic_forward")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
.padding(.horizontal, 3.3)
|
||||
.frame(width: cardWidth - 26.7, height: 50)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .privacy)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 13.3)
|
||||
.frame(width: cardWidth)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("앱 버전 정보")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Spacer()
|
||||
|
||||
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
|
||||
Text("Ver \(version!)")
|
||||
.font(.custom(Font.medium.rawValue, size: 13.3))
|
||||
.foregroundColor(Color.grayee)
|
||||
}
|
||||
.padding(.horizontal, 16.7)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Text("""
|
||||
Text("""
|
||||
- 회사명 : 주식회사 소다라이브
|
||||
|
||||
- 대표자 : 이재형
|
||||
|
@ -193,39 +196,40 @@ struct SettingsView: View {
|
|||
|
||||
- 대표 이메일 : sodalive.official@gmail.com
|
||||
""")
|
||||
.font(.custom(Font.medium.rawValue, size: 11))
|
||||
.foregroundColor(Color.gray77)
|
||||
.frame(width: cardWidth, alignment: .leading)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("로그아웃")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.onTapGesture {
|
||||
isShowLogoutDialog = true
|
||||
}
|
||||
|
||||
Text("모든 기기에서 로그아웃")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.gray77)
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
isShowLogoutAllDeviceDialog = true
|
||||
}
|
||||
|
||||
Text("회원탈퇴")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.gray77)
|
||||
.underline()
|
||||
.padding(.vertical, 26.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .signOut)
|
||||
.font(.custom(Font.medium.rawValue, size: 11))
|
||||
.foregroundColor(Color.gray77)
|
||||
.frame(width: cardWidth, alignment: .leading)
|
||||
.padding(.top, 13.3)
|
||||
|
||||
Text("로그아웃")
|
||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.grayee)
|
||||
.frame(width: cardWidth, height: 50)
|
||||
.background(Color.gray22)
|
||||
.cornerRadius(6.7)
|
||||
.onTapGesture {
|
||||
isShowLogoutDialog = true
|
||||
}
|
||||
.padding(.top, 46.7)
|
||||
|
||||
Text("모든 기기에서 로그아웃")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.gray77)
|
||||
.padding(.top, 13.3)
|
||||
.onTapGesture {
|
||||
isShowLogoutAllDeviceDialog = true
|
||||
}
|
||||
|
||||
Text("회원탈퇴")
|
||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||
.foregroundColor(Color.gray77)
|
||||
.underline()
|
||||
.padding(.vertical, 26.7)
|
||||
.onTapGesture {
|
||||
AppState.shared.setAppStep(step: .signOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +243,9 @@ struct SettingsView: View {
|
|||
ContentPlayerPlayManager.shared.resetPlayer()
|
||||
viewModel.logout {
|
||||
self.isShowLogoutDialog = false
|
||||
AppState.shared.setAppStep(step: .main)
|
||||
UserDefaults.reset()
|
||||
AppState.shared.isChangeAdultContentVisible = true
|
||||
AppState.shared.setAppStep(step: .splash)
|
||||
}
|
||||
},
|
||||
cancelButtonTitle: "취소",
|
||||
|
@ -260,8 +265,9 @@ struct SettingsView: View {
|
|||
ContentPlayerPlayManager.shared.resetPlayer()
|
||||
viewModel.logoutAllDevice {
|
||||
self.isShowLogoutAllDeviceDialog = false
|
||||
AppState.shared.setAppStep(step: .main)
|
||||
UserDefaults.reset()
|
||||
AppState.shared.isChangeAdultContentVisible = true
|
||||
AppState.shared.setAppStep(step: .splash)
|
||||
}
|
||||
},
|
||||
cancelButtonTitle: "취소",
|
||||
|
|
|
@ -56,6 +56,7 @@ final class SignOutViewModel: ObservableObject {
|
|||
|
||||
if decoded.success {
|
||||
UserDefaults.reset()
|
||||
AppState.shared.isChangeAdultContentVisible = true
|
||||
AppState.shared.setAppStep(step: .splash)
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
|
|
|
@ -11,6 +11,8 @@ import Kingfisher
|
|||
|
||||
struct SeriesListBigItemView: View {
|
||||
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
|
||||
let item: SeriesListItem
|
||||
let isVisibleCreator: Bool
|
||||
|
||||
|
@ -26,8 +28,13 @@ struct SeriesListBigItemView: View {
|
|||
.cornerRadius(5)
|
||||
.clipped()
|
||||
.onTapGesture {
|
||||
AppState.shared
|
||||
.setAppStep(step: .seriesDetail(seriesId: item.seriesId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.setAppStep(step: .seriesDetail(seriesId: item.seriesId))
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
|
@ -80,8 +87,13 @@ struct SeriesListBigItemView: View {
|
|||
.lineLimit(1)
|
||||
}
|
||||
.onTapGesture {
|
||||
AppState.shared
|
||||
.setAppStep(step: .creatorDetail(userId: item.creator.creatorId))
|
||||
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
AppState.shared
|
||||
.setAppStep(step: .creatorDetail(userId: item.creator.creatorId))
|
||||
} else {
|
||||
AppState.shared
|
||||
.setAppStep(step: .login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ struct LoginView: View {
|
|||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
HomeNavigationBar(title: "로그인") {}
|
||||
DetailNavigationBar(title: "로그인")
|
||||
|
||||
Spacer()
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ final class LoginViewModel: ObservableObject {
|
|||
UserDefaults.set(data.userId, forKey: .userId)
|
||||
UserDefaults.set(data.email, forKey: .email)
|
||||
UserDefaults.set(data.token, forKey: .token)
|
||||
AppState.shared.isChangeAdultContentVisible = true
|
||||
AppState.shared.setAppStep(step: .splash)
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
|
|
|
@ -58,7 +58,8 @@ final class SignUpViewModel: ObservableObject {
|
|||
UserDefaults.set(data.userId, forKey: .userId)
|
||||
UserDefaults.set(data.email, forKey: .email)
|
||||
UserDefaults.set(data.token, forKey: .token)
|
||||
AppState.shared.back()
|
||||
AppState.shared.isChangeAdultContentVisible = true
|
||||
AppState.shared.setAppStep(step: .splash)
|
||||
} else {
|
||||
if let message = decoded.message {
|
||||
self.errorMessage = message
|
||||
|
|
Loading…
Reference in New Issue