diff --git a/PophoryPractice/PophoryPractice.xcodeproj/project.pbxproj b/PophoryPractice/PophoryPractice.xcodeproj/project.pbxproj index 607499b..9be0273 100644 --- a/PophoryPractice/PophoryPractice.xcodeproj/project.pbxproj +++ b/PophoryPractice/PophoryPractice.xcodeproj/project.pbxproj @@ -7,7 +7,17 @@ objects = { /* Begin PBXBuildFile section */ + 3B2842F42C4944D500873964 /* pophoryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2842F32C4944D500873964 /* pophoryButton.swift */; }; + 3B33A4FA2C58EC0200CE376C /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B33A4F92C58EC0200CE376C /* OnboardingView.swift */; }; + 3B9417432C5A5727002DAE37 /* PophoryTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B9417422C5A5727002DAE37 /* PophoryTabView.swift */; }; + 3B9417462C5A5B75002DAE37 /* LoggedStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B9417452C5A5B75002DAE37 /* LoggedStateModel.swift */; }; + 3BA899812C3E735A002C4213 /* albumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA899802C3E735A002C4213 /* albumModel.swift */; }; + 3BA899842C3E7AF7002C4213 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA899832C3E7AF7002C4213 /* HomeView.swift */; }; + 3BA899862C3E7BB8002C4213 /* SelectAlbumCoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA899852C3E7BB8002C4213 /* SelectAlbumCoverView.swift */; }; + 3BA899882C3E8F46002C4213 /* AlbumIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA899872C3E8F46002C4213 /* AlbumIconView.swift */; }; 3BC648FD2C2C53CD000BDAFA /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3BC648FC2C2C53CD000BDAFA /* Colors.xcassets */; }; + 3BEA3C532C57E49C00F55311 /* MyPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3C522C57E49C00F55311 /* MyPageView.swift */; }; + 3BEA3C552C57E5CC00F55311 /* AlbumDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BEA3C542C57E5CC00F55311 /* AlbumDetailView.swift */; }; 3BFF3CF32C2C4F04001460A7 /* PophoryPracticeApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFF3CF22C2C4F04001460A7 /* PophoryPracticeApp.swift */; }; 3BFF3CF52C2C4F04001460A7 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFF3CF42C2C4F04001460A7 /* ContentView.swift */; }; 3BFF3CF72C2C4F05001460A7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3BFF3CF62C2C4F05001460A7 /* Assets.xcassets */; }; @@ -37,7 +47,17 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 3B2842F32C4944D500873964 /* pophoryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = pophoryButton.swift; sourceTree = ""; }; + 3B33A4F92C58EC0200CE376C /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; + 3B9417422C5A5727002DAE37 /* PophoryTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PophoryTabView.swift; sourceTree = ""; }; + 3B9417452C5A5B75002DAE37 /* LoggedStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedStateModel.swift; sourceTree = ""; }; + 3BA899802C3E735A002C4213 /* albumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = albumModel.swift; sourceTree = ""; }; + 3BA899832C3E7AF7002C4213 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + 3BA899852C3E7BB8002C4213 /* SelectAlbumCoverView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectAlbumCoverView.swift; sourceTree = ""; }; + 3BA899872C3E8F46002C4213 /* AlbumIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumIconView.swift; sourceTree = ""; }; 3BC648FC2C2C53CD000BDAFA /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = ""; }; + 3BEA3C522C57E49C00F55311 /* MyPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageView.swift; sourceTree = ""; }; + 3BEA3C542C57E5CC00F55311 /* AlbumDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailView.swift; sourceTree = ""; }; 3BFF3CEF2C2C4F04001460A7 /* PophoryPractice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PophoryPractice.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3BFF3CF22C2C4F04001460A7 /* PophoryPracticeApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PophoryPracticeApp.swift; sourceTree = ""; }; 3BFF3CF42C2C4F04001460A7 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -77,6 +97,55 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3B33A4F82C58EB5400CE376C /* Onboarding */ = { + isa = PBXGroup; + children = ( + 3B33A4F92C58EC0200CE376C /* OnboardingView.swift */, + ); + path = Onboarding; + sourceTree = ""; + }; + 3B9417412C5A571C002DAE37 /* TabView */ = { + isa = PBXGroup; + children = ( + 3B9417422C5A5727002DAE37 /* PophoryTabView.swift */, + ); + path = TabView; + sourceTree = ""; + }; + 3B9417442C5A5B66002DAE37 /* Model */ = { + isa = PBXGroup; + children = ( + 3B9417452C5A5B75002DAE37 /* LoggedStateModel.swift */, + ); + path = Model; + sourceTree = ""; + }; + 3BA8997F2C3E734E002C4213 /* Yunseo */ = { + isa = PBXGroup; + children = ( + 3BA899822C3E7AEE002C4213 /* View */, + 3BA899802C3E735A002C4213 /* albumModel.swift */, + ); + path = Yunseo; + sourceTree = ""; + }; + 3BA899822C3E7AEE002C4213 /* View */ = { + isa = PBXGroup; + children = ( + 3B9417442C5A5B66002DAE37 /* Model */, + 3B9417412C5A571C002DAE37 /* TabView */, + 3B33A4F82C58EB5400CE376C /* Onboarding */, + 3BA899832C3E7AF7002C4213 /* HomeView.swift */, + 3BA899852C3E7BB8002C4213 /* SelectAlbumCoverView.swift */, + 3BA899872C3E8F46002C4213 /* AlbumIconView.swift */, + 3B2842F32C4944D500873964 /* pophoryButton.swift */, + 3BEA3C522C57E49C00F55311 /* MyPageView.swift */, + 3BEA3C542C57E5CC00F55311 /* AlbumDetailView.swift */, + ); + path = View; + sourceTree = ""; + }; 3BFF3CE62C2C4F04001460A7 = { isa = PBXGroup; children = ( @@ -100,6 +169,7 @@ 3BFF3CF12C2C4F04001460A7 /* PophoryPractice */ = { isa = PBXGroup; children = ( + 3BA8997F2C3E734E002C4213 /* Yunseo */, 3BFF3CF22C2C4F04001460A7 /* PophoryPracticeApp.swift */, 3BFF3CF42C2C4F04001460A7 /* ContentView.swift */, 3BFF3CF62C2C4F05001460A7 /* Assets.xcassets */, @@ -269,8 +339,18 @@ files = ( 3BFF3CF52C2C4F04001460A7 /* ContentView.swift in Sources */, 3BFF3D1F2C2C501A001460A7 /* YunseoView.swift in Sources */, + 3B9417432C5A5727002DAE37 /* PophoryTabView.swift in Sources */, 3BFF3D1D2C2C5012001460A7 /* JoonView.swift in Sources */, + 3BA899882C3E8F46002C4213 /* AlbumIconView.swift in Sources */, + 3BA899842C3E7AF7002C4213 /* HomeView.swift in Sources */, + 3BA899812C3E735A002C4213 /* albumModel.swift in Sources */, + 3BA899862C3E7BB8002C4213 /* SelectAlbumCoverView.swift in Sources */, + 3BEA3C532C57E49C00F55311 /* MyPageView.swift in Sources */, + 3BEA3C552C57E5CC00F55311 /* AlbumDetailView.swift in Sources */, + 3B33A4FA2C58EC0200CE376C /* OnboardingView.swift in Sources */, + 3B9417462C5A5B75002DAE37 /* LoggedStateModel.swift in Sources */, 3BFF3CF32C2C4F04001460A7 /* PophoryPracticeApp.swift in Sources */, + 3B2842F42C4944D500873964 /* pophoryButton.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PophoryPractice/PophoryPractice/ContentView.swift b/PophoryPractice/PophoryPractice/ContentView.swift index 58a111e..7214910 100644 --- a/PophoryPractice/PophoryPractice/ContentView.swift +++ b/PophoryPractice/PophoryPractice/ContentView.swift @@ -8,17 +8,14 @@ import SwiftUI struct ContentView: View { + @EnvironmentObject private var appState: AppState + var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundStyle(.tint) - Text("Hello, world!") - } - .padding() + YunseoView() } } #Preview { ContentView() + .environmentObject(AppState()) } diff --git a/PophoryPractice/PophoryPractice/PophoryPracticeApp.swift b/PophoryPractice/PophoryPractice/PophoryPracticeApp.swift index 16ed5e8..1d63fc2 100644 --- a/PophoryPractice/PophoryPractice/PophoryPracticeApp.swift +++ b/PophoryPractice/PophoryPractice/PophoryPracticeApp.swift @@ -9,9 +9,12 @@ import SwiftUI @main struct PophoryPracticeApp: App { + @StateObject private var appState = AppState() + var body: some Scene { WindowGroup { - ContentView() + YunseoView() + .environmentObject(appState) } } } diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/AlbumDetailView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/AlbumDetailView.swift new file mode 100644 index 0000000..0efe2bf --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/AlbumDetailView.swift @@ -0,0 +1,18 @@ +// +// AlbumDetailView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/29/24. +// + +import SwiftUI + +struct AlbumDetailView: View { + var body: some View { + Text("Album Detail View") + } +} + +#Preview { + AlbumDetailView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/AlbumIconView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/AlbumIconView.swift new file mode 100644 index 0000000..d0eca73 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/AlbumIconView.swift @@ -0,0 +1,24 @@ +// +// AlbumIconView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/10/24. +// + +import SwiftUI + +struct AlbumIconView: View { + @Binding var isSelectedIcon: UUID + let element: AlbumIconModel + + var body: some View { + return (element.id == isSelectedIcon ? selectIcon(for: isSelectedIcon): element.iconImage) + } + + private func selectIcon(for id: UUID) -> Image { + if let index = AlbumIconModel.albumIcons.firstIndex(where: {$0.id == id}) { + return AlbumSelectIconModel.albumSelectIcons[index].iconImage + } + return Image(systemName: "circle") + } +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/HomeView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/HomeView.swift new file mode 100644 index 0000000..9932448 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/HomeView.swift @@ -0,0 +1,71 @@ +// +// HomeView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/10/24. +// + +import SwiftUI + +struct HomeView: View { + var body: some View { + NavigationStack { + VStack { + HStack { + Text("Pophory") + .font(.system(size: 40)) + .fontWeight(.heavy) + .padding(.init(top: 26, leading: 20, bottom: 0, trailing: 0)) + + Spacer() + } + + HStack { + Text("포포리 앨범에\n소중한 추억을 보관해봐!") + .padding(.leading, 20) + .font(.system(size: 24)) + .fontWeight(.semibold) + + Spacer() + + NavigationLink { + SelectAlbumCoverView() + .toolbar(.hidden, for: .tabBar) + .navigationTitle("앨범 테마") + } label: { + Image(uiImage: .add) + .padding(.top, 34) + } + + Spacer() + } + .padding(.top, 25) + + NavigationLink { + AlbumDetailView() + .toolbar(.hidden, for: .tabBar) + .navigationTitle("앨범") + } label: { + Image(.icAlbumCoverFamily1) + .resizable() + .frame(width: 280, height: 380) + .clipShape( + .rect( + topLeadingRadius: 4, + bottomLeadingRadius: 4, + bottomTrailingRadius: 26, + topTrailingRadius: 26, + style: .circular) + ) + + } + .padding(.top, 36) + Spacer() + } + } + } +} + +#Preview { + HomeView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/Model/LoggedStateModel.swift b/PophoryPractice/PophoryPractice/Yunseo/View/Model/LoggedStateModel.swift new file mode 100644 index 0000000..9a1b249 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/Model/LoggedStateModel.swift @@ -0,0 +1,12 @@ +// +// LoggedStateModel.swift +// PophoryPractice +// +// Created by 강윤서 on 7/31/24. +// + +import SwiftUI + +class AppState: ObservableObject { + @Published var isLoggedIn: Bool = false +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/MyPageView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/MyPageView.swift new file mode 100644 index 0000000..be4ec74 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/MyPageView.swift @@ -0,0 +1,18 @@ +// +// MyPageView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/29/24. +// + +import SwiftUI + +struct MyPageView: View { + var body: some View { + Text("My Page View") + } +} + +#Preview { + MyPageView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/Onboarding/OnboardingView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/Onboarding/OnboardingView.swift new file mode 100644 index 0000000..b7f6e62 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/Onboarding/OnboardingView.swift @@ -0,0 +1,59 @@ +// +// OnboardingView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/30/24. +// + +import SwiftUI + +struct OnboardingView: View { + var image: [Image] = [ + Image(.imgOnboarding01), + Image(.imgOnboarding02), + Image(.imgOnboarding03), + Image(.imgOnboarding04), + ] + @State private var selectedIndex = 0 + @EnvironmentObject private var appState: AppState + @GestureState private var dragAmount = CGSize.zero + + var body: some View { + VStack { + TabView(selection: $selectedIndex) { + ForEach(0..<4, id: \.self) { index in + image[index] + .resizable() + .scaledToFit() + .tag(index) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) + + HStack { + ForEach(0..<4) { index in + Circle() + .fill(index == selectedIndex ? .gray500 : .gray400) + .frame(width: 9, height: 9) + } + } + + Text("SNS로 간편가입하기!") + .foregroundStyle(.gray500) + .font(.system(size: 16)) + .padding(.top, 42) + + Button("AppleID로 시작하기") { + appState.isLoggedIn = true + } + .buttonStyle(PophoryButton()) + .padding([.leading, .trailing], 20) + .padding(.top, 14) + } + } +} + +#Preview { + OnboardingView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/SelectAlbumCoverView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/SelectAlbumCoverView.swift new file mode 100644 index 0000000..c8a9550 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/SelectAlbumCoverView.swift @@ -0,0 +1,68 @@ +// +// SelectAlbumCoverView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/10/24. +// + +import SwiftUI + +struct SelectAlbumCoverView: View { + @State private var selectedIcon: UUID = AlbumIconModel.albumIcons.first!.id + @Environment(\.dismiss) private var dismiss + let rows = [GridItem(.flexible())] + + var body: some View { + VStack { + Spacer() + + LazyHGrid(rows: rows, spacing: 18) { + ForEach(AlbumIconModel.albumIcons, id: \.id) { element in + AlbumIconView(isSelectedIcon: $selectedIcon, element: element) + .onTapGesture { + selectedIcon = element.id + } + } + } + .frame(width: .infinity, height: 50) + + Spacer() + + ScrollView(.horizontal) { + LazyHGrid(rows: rows, spacing: 16, content: { + ForEach(AlbumCoverModel.albumCovers, id: \.id) { element in + element.coverImage + .resizable() + .clipShape( + .rect(topLeadingRadius: 4, + bottomLeadingRadius: 4, + bottomTrailingRadius: 26, + topTrailingRadius: 26, + style: .circular) + ) + .frame(width: 280, height: 380) + } + }) + .padding([.leading, .trailing], 48) + } + .scrollIndicators(.hidden, axes: .horizontal) + .frame(width: .infinity, height: 380) + + Spacer() + + Button(action: { + dismiss() + }, label: { + Text("수정하기") + }) + .buttonStyle(PophoryButton()) + .frame(width: 335) + + Spacer() + } + } +} + +#Preview { + SelectAlbumCoverView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/TabView/PophoryTabView.swift b/PophoryPractice/PophoryPractice/Yunseo/View/TabView/PophoryTabView.swift new file mode 100644 index 0000000..17cc245 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/TabView/PophoryTabView.swift @@ -0,0 +1,31 @@ +// +// TabView.swift +// PophoryPractice +// +// Created by 강윤서 on 7/31/24. +// + +import SwiftUI + +struct PophoryTabView: View { + var body: some View { + TabView { + HomeView() + .tabItem { + Image(uiImage: .checkmark) + Text("내 서랍") + } + + MyPageView() + .tabItem { + Image(uiImage: .strokedCheckmark) + Text("마이") + } + } + .tint(.purple) + } +} + +#Preview { + PophoryTabView() +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/View/pophoryButton.swift b/PophoryPractice/PophoryPractice/Yunseo/View/pophoryButton.swift new file mode 100644 index 0000000..78faa79 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/View/pophoryButton.swift @@ -0,0 +1,22 @@ +// +// pophoryButton.swift +// PophoryPractice +// +// Created by 강윤서 on 7/18/24. +// + +import SwiftUI + +struct PophoryButton: ButtonStyle { + var height: CGFloat = 60 + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .frame(maxWidth: .infinity, maxHeight: height) + .padding([.leading, .trailing]) + .background(.black) + .foregroundStyle(.white) + .clipShape(Capsule()) + .fontWeight(.heavy) + } +} diff --git a/PophoryPractice/PophoryPractice/Yunseo/albumModel.swift b/PophoryPractice/PophoryPractice/Yunseo/albumModel.swift new file mode 100644 index 0000000..b476d45 --- /dev/null +++ b/PophoryPractice/PophoryPractice/Yunseo/albumModel.swift @@ -0,0 +1,54 @@ +// +// listModel.swift +// PophoryPractice +// +// Created by 강윤서 on 7/10/24. +// + +import SwiftUI + +struct AlbumCoverModel: Identifiable { + let id = UUID() + let coverImage: Image +} + +struct AlbumIconModel: Identifiable { + let id = UUID() + let iconImage: Image +} + +struct AlbumSelectIconModel: Identifiable { + let id = UUID() + let iconImage: Image +} + +extension AlbumCoverModel { + static var albumCovers: [AlbumCoverModel] = [ + AlbumCoverModel(coverImage: Image(.icAlbumCoverFamily1)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverFamily2)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverLove1)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverLove2)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverFriends1)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverFriends2)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverMe1)), + AlbumCoverModel(coverImage: Image(.icAlbumCoverMe2)), + ] +} + +extension AlbumIconModel { + static var albumIcons: [AlbumIconModel] = [ + AlbumIconModel(iconImage: Image(.albumCover1)), + AlbumIconModel(iconImage: Image(.albumCover2)), + AlbumIconModel(iconImage: Image(.albumCover3)), + AlbumIconModel(iconImage: Image(.albumCover4)) + ] +} + +extension AlbumSelectIconModel { + static var albumSelectIcons: [AlbumSelectIconModel] = [ + AlbumSelectIconModel(iconImage: Image(.albumCoverProfile1)), + AlbumSelectIconModel(iconImage: Image(.albumCoverProfile2)), + AlbumSelectIconModel(iconImage: Image(.albumCoverProfile3)), + AlbumSelectIconModel(iconImage: Image(.albumCoverProfile4)) + ] +} diff --git a/PophoryPractice/PophoryPractice/YunseoView.swift b/PophoryPractice/PophoryPractice/YunseoView.swift index 97dc054..22b9af7 100644 --- a/PophoryPractice/PophoryPractice/YunseoView.swift +++ b/PophoryPractice/PophoryPractice/YunseoView.swift @@ -8,11 +8,20 @@ import SwiftUI struct YunseoView: View { + @EnvironmentObject var appState: AppState + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Group { + if appState.isLoggedIn { + PophoryTabView() + } else { + OnboardingView() + } + } } } #Preview { YunseoView() + .environmentObject(AppState()) }