diff --git a/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/Contents.json b/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/Contents.json new file mode 100644 index 0000000..6263181 --- /dev/null +++ b/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/Contents.json @@ -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 + } +} diff --git a/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/ic_logo_circle_gray.png b/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/ic_logo_circle_gray.png new file mode 100644 index 0000000..f740d7c Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/ic_logo_circle_gray.imageset/ic_logo_circle_gray.png differ diff --git a/SodaLive/Sources/App/AppStep.swift b/SodaLive/Sources/App/AppStep.swift index 684d6af..fc6d484 100644 --- a/SodaLive/Sources/App/AppStep.swift +++ b/SodaLive/Sources/App/AppStep.swift @@ -12,6 +12,8 @@ enum AppStep { case main + case login + case signUp case findPassword diff --git a/SodaLive/Sources/Audition/AuditionApi.swift b/SodaLive/Sources/Audition/AuditionApi.swift index 66101e2..79e5952 100644 --- a/SodaLive/Sources/Audition/AuditionApi.swift +++ b/SodaLive/Sources/Audition/AuditionApi.swift @@ -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))"] + } } } diff --git a/SodaLive/Sources/Audition/AuditionView.swift b/SodaLive/Sources/Audition/AuditionView.swift index aa14ec5..e52f983 100644 --- a/SodaLive/Sources/Audition/AuditionView.swift +++ b/SodaLive/Sources/Audition/AuditionView.swift @@ -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) } } } diff --git a/SodaLive/Sources/Content/ContentApi.swift b/SodaLive/Sources/Content/ContentApi.swift index 9f2ccbe..cd26cfa 100644 --- a/SodaLive/Sources/Content/ContentApi.swift +++ b/SodaLive/Sources/Content/ContentApi.swift @@ -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, diff --git a/SodaLive/Sources/Content/Main/V2/Content/ContentMainTabRankContentView.swift b/SodaLive/Sources/Content/Main/V2/Content/ContentMainTabRankContentView.swift index 9b50460..3188190 100644 --- a/SodaLive/Sources/Content/Main/V2/Content/ContentMainTabRankContentView.swift +++ b/SodaLive/Sources/Content/Main/V2/Content/ContentMainTabRankContentView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/Content/Main/V2/ContentByChannelView.swift b/SodaLive/Sources/Content/Main/V2/ContentByChannelView.swift index fa0bbb4..839149e 100644 --- a/SodaLive/Sources/Content/Main/V2/ContentByChannelView.swift +++ b/SodaLive/Sources/Content/Main/V2/ContentByChannelView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeRepository.swift b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeRepository.swift index 387e26c..112c564 100644 --- a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeRepository.swift +++ b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeRepository.swift @@ -31,4 +31,14 @@ class ContentMainTabHomeRepository { ) ) } + + func getContentRanking(sortType: String = "매출") -> AnyPublisher { + return api.requestPublisher( + .getContentMainHomeContentRanking( + isAdultContentVisible: UserDefaults.isAdultContentVisible(), + contentType: ContentType(rawValue: UserDefaults.string(forKey: .contentPreference)) ?? ContentType.ALL, + sortType: sortType + ) + ) + } } diff --git a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeView.swift b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeView.swift index 3e7498a..f22d38d 100644 --- a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeView.swift +++ b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeView.swift @@ -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) } diff --git a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeViewModel.swift b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeViewModel.swift index 8e30cb0..fd222e4 100644 --- a/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeViewModel.swift +++ b/SodaLive/Sources/Content/Main/V2/Home/ContentMainTabHomeViewModel.swift @@ -11,7 +11,6 @@ import Combine final class ContentMainTabHomeViewModel: ObservableObject { private let repository = ContentMainTabHomeRepository() - private let contentRepository = ContentRepository() private var subscription = Set() @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.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 diff --git a/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift b/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift index a1a16c8..93bf959 100644 --- a/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift +++ b/SodaLive/Sources/Content/Main/V2/Home/Rank/ContentMainTabHomeRankCreatorView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/ContentView.swift b/SodaLive/Sources/ContentView.swift index 33a40d2..6626fa8 100644 --- a/SodaLive/Sources/ContentView.swift +++ b/SodaLive/Sources/ContentView.swift @@ -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() diff --git a/SodaLive/Sources/Live/EventBanner/SectionEventBannerView.swift b/SodaLive/Sources/Live/EventBanner/SectionEventBannerView.swift index 0879ee5..bfa8449 100644 --- a/SodaLive/Sources/Live/EventBanner/SectionEventBannerView.swift +++ b/SodaLive/Sources/Live/EventBanner/SectionEventBannerView.swift @@ -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) } } } diff --git a/SodaLive/Sources/Live/LiveView.swift b/SodaLive/Sources/Live/LiveView.swift index 550abb0..786a044 100644 --- a/SodaLive/Sources/Live/LiveView.swift +++ b/SodaLive/Sources/Live/LiveView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/Live/LiveViewModel.swift b/SodaLive/Sources/Live/LiveViewModel.swift index ffe2d1d..d1b529e 100644 --- a/SodaLive/Sources/Live/LiveViewModel.swift +++ b/SodaLive/Sources/Live/LiveViewModel.swift @@ -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() diff --git a/SodaLive/Sources/Live/Now/SectionLiveNowView.swift b/SodaLive/Sources/Live/Now/SectionLiveNowView.swift index ec0e553..eabae12 100644 --- a/SodaLive/Sources/Live/Now/SectionLiveNowView.swift +++ b/SodaLive/Sources/Live/Now/SectionLiveNowView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/Live/Recommend/SectionRecommendLiveView.swift b/SodaLive/Sources/Live/Recommend/SectionRecommendLiveView.swift index 759a3a2..2856759 100644 --- a/SodaLive/Sources/Live/Recommend/SectionRecommendLiveView.swift +++ b/SodaLive/Sources/Live/Recommend/SectionRecommendLiveView.swift @@ -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) } diff --git a/SodaLive/Sources/Live/RecommendChannel/SectionRecommendChannelView.swift b/SodaLive/Sources/Live/RecommendChannel/SectionRecommendChannelView.swift index 1d4c0a7..5cb3642 100644 --- a/SodaLive/Sources/Live/RecommendChannel/SectionRecommendChannelView.swift +++ b/SodaLive/Sources/Live/RecommendChannel/SectionRecommendChannelView.swift @@ -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) } } } diff --git a/SodaLive/Sources/Live/Reservation/SectionLiveReservationView.swift b/SodaLive/Sources/Live/Reservation/SectionLiveReservationView.swift index b0edd21..84f7f67 100644 --- a/SodaLive/Sources/Live/Reservation/SectionLiveReservationView.swift +++ b/SodaLive/Sources/Live/Reservation/SectionLiveReservationView.swift @@ -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) + } } } } diff --git a/SodaLive/Sources/Main/Home/HomeView.swift b/SodaLive/Sources/Main/Home/HomeView.swift index 03af700..36a9402 100644 --- a/SodaLive/Sources/Main/Home/HomeView.swift +++ b/SodaLive/Sources/Main/Home/HomeView.swift @@ -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 { diff --git a/SodaLive/Sources/Main/MainView.swift b/SodaLive/Sources/Main/MainView.swift deleted file mode 100644 index 78bf6bb..0000000 --- a/SodaLive/Sources/Main/MainView.swift +++ /dev/null @@ -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() - } -} diff --git a/SodaLive/Sources/MyPage/MyPageView.swift b/SodaLive/Sources/MyPage/MyPageView.swift index 5e73c91..094be81 100644 --- a/SodaLive/Sources/MyPage/MyPageView.swift +++ b/SodaLive/Sources/MyPage/MyPageView.swift @@ -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() + } } } } diff --git a/SodaLive/Sources/MyPage/ServiceCenter/FaqApi.swift b/SodaLive/Sources/MyPage/ServiceCenter/FaqApi.swift index 4b280e2..441b41b 100644 --- a/SodaLive/Sources/MyPage/ServiceCenter/FaqApi.swift +++ b/SodaLive/Sources/MyPage/ServiceCenter/FaqApi.swift @@ -43,6 +43,6 @@ extension FaqApi: TargetType { } var headers: [String : String]? { - return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"] + return nil } } diff --git a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterButtonView.swift b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterButtonView.swift index d72a561..8f459eb 100644 --- a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterButtonView.swift +++ b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterButtonView.swift @@ -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) diff --git a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift index aa528f1..413dc23 100644 --- a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift +++ b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift @@ -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, diff --git a/SodaLive/Sources/Settings/SettingsView.swift b/SodaLive/Sources/Settings/SettingsView.swift index 2823196..e816fd7 100644 --- a/SodaLive/Sources/Settings/SettingsView.swift +++ b/SodaLive/Sources/Settings/SettingsView.swift @@ -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: "취소", diff --git a/SodaLive/Sources/Settings/SignOut/SignOutViewModel.swift b/SodaLive/Sources/Settings/SignOut/SignOutViewModel.swift index f54af01..20d585e 100644 --- a/SodaLive/Sources/Settings/SignOut/SignOutViewModel.swift +++ b/SodaLive/Sources/Settings/SignOut/SignOutViewModel.swift @@ -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 { diff --git a/SodaLive/Sources/UI/Component/SeriesListBigItemView.swift b/SodaLive/Sources/UI/Component/SeriesListBigItemView.swift index 84eed17..90e6925 100644 --- a/SodaLive/Sources/UI/Component/SeriesListBigItemView.swift +++ b/SodaLive/Sources/UI/Component/SeriesListBigItemView.swift @@ -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) + } } } diff --git a/SodaLive/Sources/User/Login/LoginView.swift b/SodaLive/Sources/User/Login/LoginView.swift index db954ac..bde598f 100644 --- a/SodaLive/Sources/User/Login/LoginView.swift +++ b/SodaLive/Sources/User/Login/LoginView.swift @@ -17,7 +17,7 @@ struct LoginView: View { var body: some View { BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { - HomeNavigationBar(title: "로그인") {} + DetailNavigationBar(title: "로그인") Spacer() diff --git a/SodaLive/Sources/User/Login/LoginViewModel.swift b/SodaLive/Sources/User/Login/LoginViewModel.swift index e5b5ac8..7750d08 100644 --- a/SodaLive/Sources/User/Login/LoginViewModel.swift +++ b/SodaLive/Sources/User/Login/LoginViewModel.swift @@ -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 diff --git a/SodaLive/Sources/User/SignUp/SignUpViewModel.swift b/SodaLive/Sources/User/SignUp/SignUpViewModel.swift index 5349347..63d06e6 100644 --- a/SodaLive/Sources/User/SignUp/SignUpViewModel.swift +++ b/SodaLive/Sources/User/SignUp/SignUpViewModel.swift @@ -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