diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index e68c9c0a..a2ec4dac 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -33,9 +33,12 @@ 8786B33C29ABA588000B46A1 /* View+Gesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8786B33B29ABA588000B46A1 /* View+Gesture.swift */; }; 8786B33E29ABA5A9000B46A1 /* View+Shape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8786B33D29ABA5A9000B46A1 /* View+Shape.swift */; }; 8788374A2920D549009B3F54 /* Binding+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 878837492920D549009B3F54 /* Binding+Extension.swift */; }; + 8788E19D2A475AB3007C3852 /* ListCurationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8788E19C2A475AB3007C3852 /* ListCurationViewModel.swift */; }; + 8788E1A02A48408F007C3852 /* ExploreCurationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8788E19F2A48408F007C3852 /* ExploreCurationViewModel.swift */; }; 8792478D2918CE450040D5C3 /* UINavigationContoller+Gesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8792478C2918CE450040D5C3 /* UINavigationContoller+Gesture.swift */; }; 8792479B291BDF820040D5C3 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8792479A291BDF820040D5C3 /* SearchView.swift */; }; 8795A170292AB945004B765F /* UIScreen+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8795A16F292AB945004B765F /* UIScreen+Size.swift */; }; + 87B47F3B2A3DC2740009E75F /* ReadCurationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87B47F3A2A3DC2740009E75F /* ReadCurationViewModel.swift */; }; 87CFD8492939187200F97B86 /* NicknameTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87CFD8482939187200F97B86 /* NicknameTextField.swift */; }; 87DBFB062A2127C0000CC442 /* CheckVersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87DBFB052A2127C0000CC442 /* CheckVersionView.swift */; }; 87E606B0291062F900C3DA13 /* AppleAuthCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E606AF291062F900C3DA13 /* AppleAuthCoordinator.swift */; }; @@ -203,9 +206,12 @@ 8786B33B29ABA588000B46A1 /* View+Gesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Gesture.swift"; sourceTree = ""; }; 8786B33D29ABA5A9000B46A1 /* View+Shape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Shape.swift"; sourceTree = ""; }; 878837492920D549009B3F54 /* Binding+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+Extension.swift"; sourceTree = ""; }; + 8788E19C2A475AB3007C3852 /* ListCurationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCurationViewModel.swift; sourceTree = ""; }; + 8788E19F2A48408F007C3852 /* ExploreCurationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreCurationViewModel.swift; sourceTree = ""; }; 8792478C2918CE450040D5C3 /* UINavigationContoller+Gesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationContoller+Gesture.swift"; sourceTree = ""; }; 8792479A291BDF820040D5C3 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; 8795A16F292AB945004B765F /* UIScreen+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScreen+Size.swift"; sourceTree = ""; }; + 87B47F3A2A3DC2740009E75F /* ReadCurationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadCurationViewModel.swift; sourceTree = ""; }; 87CFD8482939187200F97B86 /* NicknameTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NicknameTextField.swift; sourceTree = ""; }; 87DBFB052A2127C0000CC442 /* CheckVersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckVersionView.swift; sourceTree = ""; }; 87E606AD2910623C00C3DA13 /* HappyAnding.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HappyAnding.entitlements; sourceTree = ""; }; @@ -356,6 +362,51 @@ path = View; sourceTree = ""; }; + 8788E19E2A483FDF007C3852 /* ExploreCurationViewModels */ = { + isa = PBXGroup; + children = ( + 87B47F3A2A3DC2740009E75F /* ReadCurationViewModel.swift */, + 8788E19C2A475AB3007C3852 /* ListCurationViewModel.swift */, + 8788E19F2A48408F007C3852 /* ExploreCurationViewModel.swift */, + ); + path = ExploreCurationViewModels; + sourceTree = ""; + }; + 8788E1A12A484518007C3852 /* ExploreShortcutViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = ExploreShortcutViewModels; + sourceTree = ""; + }; + 8788E1A22A484528007C3852 /* WriteShortcutViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = WriteShortcutViewModels; + sourceTree = ""; + }; + 8788E1A32A484533007C3852 /* ReadShortcutViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = ReadShortcutViewModels; + sourceTree = ""; + }; + 8788E1A42A484542007C3852 /* WriteCurationViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = WriteCurationViewModels; + sourceTree = ""; + }; + 8788E1A52A48456E007C3852 /* MyPageViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = MyPageViewModels; + sourceTree = ""; + }; 87E606AE291062D300C3DA13 /* SignInViews */ = { isa = PBXGroup; children = ( @@ -593,6 +644,12 @@ A0F822AA2910B8B900AF4448 /* ViewModel */ = { isa = PBXGroup; children = ( + 8788E1A12A484518007C3852 /* ExploreShortcutViewModels */, + 8788E1A22A484528007C3852 /* WriteShortcutViewModels */, + 8788E1A32A484533007C3852 /* ReadShortcutViewModels */, + 8788E19E2A483FDF007C3852 /* ExploreCurationViewModels */, + 8788E1A42A484542007C3852 /* WriteCurationViewModels */, + 8788E1A52A48456E007C3852 /* MyPageViewModels */, A0F822AB2910B8F100AF4448 /* ShortcutsZipViewModel.swift */, 4D61A766291E1EE8000EF531 /* NavigationViewModel.swift */, F9AC2BB52935201C00165820 /* CheckUpdateVersion.swift */, @@ -881,6 +938,7 @@ 4D7D16072986BBD7008B3332 /* TextLiteral.swift in Sources */, 87E99CC128FFF2B5009B691F /* CategoryModalView.swift in Sources */, 87E606B829114FB200C3DA13 /* UserAuth.swift in Sources */, + 8788E1A02A48408F007C3852 /* ExploreCurationViewModel.swift in Sources */, 8786B33E29ABA5A9000B46A1 /* View+Shape.swift in Sources */, A3C404D62A23D0E800C3BA75 /* UpdateInfoView.swift in Sources */, F91A72C1299915C500CA135A /* MoreCaptionTextView.swift in Sources */, @@ -903,6 +961,7 @@ 87E606B22910649B00C3DA13 /* SignInWithAppleView.swift in Sources */, F91F09DF29AE0B5E00E04FA0 /* GradeAlertView.swift in Sources */, 87E99CEC29080C30009B691F /* Curation.swift in Sources */, + 8788E19D2A475AB3007C3852 /* ListCurationViewModel.swift in Sources */, F9136EB6293612310034AAB2 /* ShortcutsZipView.swift in Sources */, 87E99CB128FFF273009B691F /* WriteCurationSetView.swift in Sources */, 4D61A767291E1EE8000EF531 /* NavigationViewModel.swift in Sources */, @@ -927,6 +986,7 @@ F9724BBF292755E400860F8A /* Comment.swift in Sources */, 87E99CA328FFF22E009B691F /* ExploreCurationView.swift in Sources */, A0F822B729164D2300AF4448 /* ListCategoryShortcutView.swift in Sources */, + 87B47F3B2A3DC2740009E75F /* ReadCurationViewModel.swift in Sources */, 872B5D3D2A2E0FF9008DCC57 /* CurationType.swift in Sources */, 4D3DBB88292E67E600DE8160 /* EditNicknameView.swift in Sources */, 87E99CE82907C6E6009B691F /* Shortcuts.swift in Sources */, diff --git a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift index 4e6df8e1..d3722e17 100644 --- a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift +++ b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift @@ -81,10 +81,10 @@ extension View { ListShortcutView(data: data as! NavigationListShortcutType) case is NavigationReadShortcutType: ReadShortcutView(data: data as! NavigationReadShortcutType) - case is NavigationReadCurationType: - ReadCurationView(data: data as! NavigationReadCurationType) + case is Curation: + ReadCurationView(viewModel: ReadCurationViewModel(data: data as! Curation)) case is CurationType: - ListCurationView(curationType: data as! CurationType) + ListCurationView(viewModel: ListCurationViewModel(data: data as! CurationType)) case is NavigationProfile: ShowProfileView(data: data as! NavigationProfile) case is NavigationSearch: @@ -118,11 +118,11 @@ struct NavigationViewModifier: ViewModifier { .navigationDestination(for: NavigationProfile.self) { data in ShowProfileView(data: data) } - .navigationDestination(for: NavigationReadCurationType.self) { data in - ReadCurationView(data: data) + .navigationDestination(for: Curation.self) { data in + ReadCurationView(viewModel: ReadCurationViewModel(data: data)) } .navigationDestination(for: CurationType.self) { data in - ListCurationView(curationType: data) + ListCurationView(viewModel: ListCurationViewModel(data: data)) } .navigationDestination(for: NavigationReadShortcutType.self) { data in ReadShortcutView(data: data) diff --git a/HappyAnding/HappyAnding/Model/Curation.swift b/HappyAnding/HappyAnding/Model/Curation.swift index 664a3445..1ef2833c 100644 --- a/HappyAnding/HappyAnding/Model/Curation.swift +++ b/HappyAnding/HappyAnding/Model/Curation.swift @@ -22,6 +22,28 @@ struct Curation: Identifiable, Equatable, Codable, Hashable { let data = (try? JSONEncoder().encode(self)) ?? Data() return (try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any]) ?? [:] } + + init(title: String, subtitle: String, isAdmin: Bool, background: String, author: String, shortcuts: [ShortcutCellModel]) { + self.id = UUID().uuidString + self.title = title + self.subtitle = subtitle + self.dateTime = Date().getDate() + self.isAdmin = isAdmin + self.background = background + self.author = author + self.shortcuts = shortcuts + } + + init() { + self.id = UUID().uuidString + self.title = "" + self.subtitle = "" + self.dateTime = Date().getDate() + self.isAdmin = false + self.background = "" + self.author = "" + self.shortcuts = [] + } } struct ShortcutCellModel: Identifiable, Codable, Equatable, Hashable { diff --git a/HappyAnding/HappyAnding/Model/NavigationStackModel.swift b/HappyAnding/HappyAnding/Model/NavigationStackModel.swift index 0a4d41a7..5760ec24 100644 --- a/HappyAnding/HappyAnding/Model/NavigationStackModel.swift +++ b/HappyAnding/HappyAnding/Model/NavigationStackModel.swift @@ -23,21 +23,6 @@ struct NavigationReadShortcutType: Identifiable, Hashable { let navigationParentView: NavigationParentView } -struct NavigationReadCurationType: Identifiable, Hashable { - var id = UUID().uuidString - - var isAdmin: Bool = false - let curation: Curation - let navigationParentView: NavigationParentView -} - -struct NavigationListCurationType: Identifiable, Hashable { - var id = UUID().uuidString - - var type: CurationType - let navigationParentView: NavigationParentView -} - struct NavigationProfile: Identifiable, Hashable { var id = UUID().uuidString diff --git a/HappyAnding/HappyAnding/Model/User.swift b/HappyAnding/HappyAnding/Model/User.swift index 7c482f69..6ce01633 100644 --- a/HappyAnding/HappyAnding/Model/User.swift +++ b/HappyAnding/HappyAnding/Model/User.swift @@ -17,6 +17,20 @@ struct User: Identifiable, Codable, Hashable { let data = (try? JSONEncoder().encode(self)) ?? Data() return (try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any]) ?? [:] } + + init() { + self.id = "" + self.nickname = "" + self.likedShortcuts = [] + self.downloadedShortcuts = [] + } + + init(id: String, nickname: String, likedShortcuts: [String], downloadedShortcuts: [DownloadedShortcut]) { + self.id = id + self.nickname = nickname + self.likedShortcuts = likedShortcuts + self.downloadedShortcuts = downloadedShortcuts + } } struct DownloadedShortcut: Identifiable, Codable, Hashable { diff --git a/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ExploreCurationViewModel.swift b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ExploreCurationViewModel.swift new file mode 100644 index 00000000..e7f57a8c --- /dev/null +++ b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ExploreCurationViewModel.swift @@ -0,0 +1,36 @@ +// +// ExploreCurationViewModel.swift +// HappyAnding +// +// Created by 이지원 on 2023/06/25. +// + +import Foundation + +final class ExploreCurationViewModel: ObservableObject { + private let shortcutsZipViewModel = ShortcutsZipViewModel.share + @Published var adminCurationList = [Curation]() + @Published var personalCurationList = [Curation]() + @Published var userCurationList = [Curation]() + + init() { + fetchAdminCurationList() + } + + private func fetchAdminCurationList() { + self.adminCurationList = shortcutsZipViewModel.adminCurations + } + + func getCurationList(with curationType: CurationType) -> [Curation] { + curationType.filterCuration(from: shortcutsZipViewModel) + } + + func getSectionTitle(with curationType: CurationType) -> String { + switch curationType { + case .personalCuration: + return (shortcutsZipViewModel.userInfo?.nickname ?? "") + curationType.title + default: + return curationType.title + } + } +} diff --git a/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ListCurationViewModel.swift b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ListCurationViewModel.swift new file mode 100644 index 00000000..23082377 --- /dev/null +++ b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ListCurationViewModel.swift @@ -0,0 +1,36 @@ +// +// ListCurationViewModel.swift +// HappyAnding +// +// Created by 이지원 on 2023/06/25. +// + +import Foundation + +final class ListCurationViewModel: ObservableObject { + private let shortcutsZipViewModel = ShortcutsZipViewModel.share + + @Published var curationType: CurationType + @Published private(set) var curationList = [Curation]() + @Published private(set) var sectionTitle: String = "" + + init(data: CurationType) { + self.curationType = data + self.curationList = curationType.filterCuration(from: shortcutsZipViewModel) + self.sectionTitle = fetchSectionTitle() + print("new viewModel: ", curationType, curationList) + } + + private func fetchSectionTitle() -> String { + switch curationType { + case .personalCuration: + return (shortcutsZipViewModel.userInfo?.nickname ?? "") + curationType.title + default: + return curationType.title + } + } + + func getEmptyContentsWording() -> String { + "아직 \(sectionTitle)\(sectionTitle.contains("단축어") ? "가" : "이") 없어요" + } +} diff --git a/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ReadCurationViewModel.swift b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ReadCurationViewModel.swift new file mode 100644 index 00000000..f65a0ecc --- /dev/null +++ b/HappyAnding/HappyAnding/ViewModel/ExploreCurationViewModels/ReadCurationViewModel.swift @@ -0,0 +1,56 @@ +// +// ReadCurationViewModel.swift +// HappyAnding +// +// Created by 이지원 on 2023/06/17. +// + +import SwiftUI + + +final class ReadCurationViewModel: ObservableObject { + private let shortcutsZipViewModel = ShortcutsZipViewModel.share + + @Published var isWriting = false + @Published var isTappedDeleteButton = false + @Published var curation: Curation + @Published private(set) var authInformation: User + @Published private(set) var gradeImage = Image(systemName: "person.crop.circle.fill") + @Published private(set) var isAdmin = false + + init(data: Curation) { + self.curation = data + self.authInformation = User() + self.isAdmin = curation.isAdmin + fetchUserGrade() + } + + private func fetchUserGrade() { + shortcutsZipViewModel.fetchUser(userID: curation.author, + isCurrentUser: false) { user in + self.authInformation = user + let grade = self.shortcutsZipViewModel.checkShortcutGrade(userID: self.authInformation.id) + let image = self.shortcutsZipViewModel.fetchShortcutGradeImage(isBig: false, shortcutGrade: grade) + self.gradeImage = image + } + } + + func checkAuthor() -> Bool { + return curation.author == shortcutsZipViewModel.currentUser() + } + + func deleteCuration() { + shortcutsZipViewModel.deleteData(model: curation) + shortcutsZipViewModel.curationsMadeByUser = shortcutsZipViewModel.curationsMadeByUser.filter { $0.id != curation.id } + } + + func shareCuration() { + guard let deepLink = URL(string: "ShortcutsZip://myPage/CurationDetailView?curationID=\(curation.id)") else { return } + + let activityVC = UIActivityViewController(activityItems: [deepLink], applicationActivities: nil) + let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene + guard let window = windowScene?.windows.first else { return } + window.rootViewController?.present(activityVC, animated: true, completion: nil) + } +} + diff --git a/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift b/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift index 61208df4..6e3c3d64 100644 --- a/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift +++ b/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift @@ -32,7 +32,11 @@ class ShortcutsZipViewModel: ObservableObject { @Published var shortcutsInCategory: [[Shortcuts]] = [[Shortcuts]].init(repeating: [], count: Category.allCases.count) // Category에서 사용할 숏컷 배열 @Published var curationsMadeByUser: [Curation] = [] // 유저가 만든 큐레이션배열 - @Published var userCurations: [Curation] = [] + @Published var userCurations: [Curation] = [] { + didSet { + self.refreshPersonalCurations() + } + } @Published var personalCurations: [Curation] = [] // "땡땡님을 위한 모음집" 큐레이션배열 @Published var adminCurations: [Curation] = [] diff --git a/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift b/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift index bddd709b..fc2bd461 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift @@ -14,7 +14,6 @@ struct UserCurationCell: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @State var curation: Curation - @State var index = 0 var lineLimit: Int? let navigationParentView: NavigationParentView @@ -25,7 +24,7 @@ struct UserCurationCell: View { //MARK: - 단축어 아이콘 배열 HStack { - ForEach(shortcutsZipViewModel.userCurations[index].shortcuts.prefix(4), id: \.self) { shortcut in + ForEach(curation.shortcuts.prefix(4), id: \.self) { shortcut in ZStack { Rectangle() .fill(Color.fetchGradient(color: shortcut.color)) @@ -38,7 +37,7 @@ struct UserCurationCell: View { } //단축어가 4개 이상인 경우에만 그리는 아이콘 - if shortcutsZipViewModel.userCurations[index].shortcuts.count > 4 { + if curation.shortcuts.count > 4 { ZStack(alignment: .center) { Rectangle() .fill(Color.gray2) @@ -47,7 +46,7 @@ struct UserCurationCell: View { HStack(spacing: 0) { Image(systemName: "plus") .smallIcon() - Text("\(shortcutsZipViewModel.userCurations[index].shortcuts.count-4)") + Text("\(curation.shortcuts.count-4)") .shortcutsZipFootnote() } .foregroundColor(.gray5) @@ -59,11 +58,11 @@ struct UserCurationCell: View { //MARK: - curation title, subtitle - Text(shortcutsZipViewModel.userCurations[index].title) + Text(curation.title) .shortcutsZipHeadline() .foregroundColor(Color.gray5) .frame(maxWidth: .infinity, alignment: .leading) - Text(shortcutsZipViewModel.userCurations[index].subtitle.lineBreaking) + Text(curation.subtitle.lineBreaking) .shortcutsZipBody2() .multilineTextAlignment(.leading) .lineLimit(lineLimit) @@ -71,11 +70,6 @@ struct UserCurationCell: View { .padding(.bottom, 20) .fixedSize(horizontal: false, vertical: true) } - .onAppear() { - if let index = shortcutsZipViewModel.userCurations.firstIndex(of: curation) { - self.index = index - } - } .padding(.horizontal, 24) .background(Color.backgroudList) .overlay( diff --git a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift index 936f4c45..2e45eae7 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift @@ -18,6 +18,7 @@ struct UserCurationListView: View { @State var isWriting = false @State var data: CurationType + @State var curation = Curation() var body: some View { VStack(spacing: 0) { @@ -58,12 +59,10 @@ struct UserCurationListView: View { ForEach(Array(shortcutsZipViewModel.curationsMadeByUser.enumerated()), id: \.offset) { index, curation in if index < 2 { - let data = NavigationReadCurationType(curation: curation, - navigationParentView: .curations) UserCurationCell(curation: curation, lineLimit: 2, navigationParentView: .curations) - .navigationLinkRouter(data: data) + .navigationLinkRouter(data: curation) } } @@ -78,9 +77,7 @@ struct UserCurationListView: View { @ViewBuilder private func writeCurationView() -> some View { - WriteCurationSetView(isWriting: $isWriting - , isEdit: false - ) + WriteCurationSetView(isWriting: $isWriting, curation: $curation, isEdit: false) .navigationDestination(for: WriteCurationInfoType.self) { data in WriteCurationInfoView(data: data, isWriting: $isWriting) } diff --git a/HappyAnding/HappyAnding/Views/Components/UserNameCell.swift b/HappyAnding/HappyAnding/Views/Components/UserNameCell.swift index af160989..ab5dd37a 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserNameCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserNameCell.swift @@ -31,9 +31,15 @@ struct UserNameCell: View { .frame(width: 24, height: 24) .foregroundColor(.gray3) - Text(userInformation?.nickname ?? TextLiteral.withdrawnUser) - .shortcutsZipBody2() - .foregroundColor(.gray4) + if let userInformation, !userInformation.nickname.isEmpty { + Text(userInformation.nickname) + .shortcutsZipBody2() + .foregroundColor(.gray4) + } else { + Text(TextLiteral.withdrawnUser) + .shortcutsZipBody2() + .foregroundColor(.gray4) + } Spacer() diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift index 78014dd2..86e29f7f 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift @@ -9,8 +9,7 @@ import SwiftUI struct ExploreCurationView: View { - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - + @StateObject var viewModel: ExploreCurationViewModel @AppStorage("useWithoutSignIn") var useWithoutSignIn = false var body: some View { @@ -27,9 +26,6 @@ struct ExploreCurationView: View { } .padding(.top, 20) .padding(.bottom, 44) - .onChange(of: shortcutsZipViewModel.userCurations) { _ in - shortcutsZipViewModel.refreshPersonalCurations() - } } .navigationBarTitle(TextLiteral.exploreCurationViewTitle) .navigationBarTitleDisplayMode(.large) @@ -48,11 +44,9 @@ struct ExploreCurationView: View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 0) { - ForEach(shortcutsZipViewModel.adminCurations, id: \.id) { curation in + ForEach(viewModel.adminCurationList, id: \.id) { curation in AdminCurationCell(adminCuration: curation) - .navigationLinkRouter(data: NavigationReadCurationType(isAdmin: true, - curation: curation, - navigationParentView: .curations)) + .navigationLinkRouter(data: curation) } } .padding(.trailing, 8) @@ -64,19 +58,10 @@ struct ExploreCurationView: View { @ViewBuilder private func sectionView(with sectionType: CurationType) -> some View { - let curations = sectionType.filterCuration(from: shortcutsZipViewModel) - var sectionTitle: String { - if sectionType == .personalCuration { - return (shortcutsZipViewModel.userInfo?.nickname ?? "") + sectionType.title - } else { - return sectionType.title - } - } - VStack(spacing: 0) { HStack(alignment: .bottom) { - SubtitleTextView(text: sectionTitle) + SubtitleTextView(text: viewModel.getSectionTitle(with: sectionType)) Spacer() @@ -86,14 +71,12 @@ struct ExploreCurationView: View { .padding(.bottom, 12) .padding(.horizontal, 16) - ForEach(curations.prefix(2), id: \.self) { curation in - let data = NavigationReadCurationType(curation: curation, - navigationParentView: .curations) + ForEach(viewModel.getCurationList(with:sectionType).prefix(2), id: \.self) { curation in UserCurationCell(curation: curation, lineLimit: 2, navigationParentView: .curations) - .navigationLinkRouter(data: data) + .navigationLinkRouter(data: curation) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift index 08cd740e..70f0dcc8 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift @@ -15,23 +15,12 @@ import SwiftUI struct ListCurationView: View { - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - - @State var curationType: CurationType - @State var curations = [Curation]() - - private var sectionTitle: String { - if curationType == .personalCuration { - return (shortcutsZipViewModel.userInfo?.nickname ?? "") + curationType.title - } else { - return curationType.title - } - } + @StateObject var viewModel: ListCurationViewModel var body: some View { VStack { - if curations.isEmpty { - Text("아직 \(sectionTitle)\(sectionTitle.contains("단축어") ? "가" : "이") 없어요") + if viewModel.curationList.isEmpty { + Text(viewModel.getEmptyContentsWording()) .shortcutsZipBody2() .foregroundColor(Color.gray4) .frame(maxWidth: .infinity, maxHeight: .infinity) @@ -41,7 +30,7 @@ struct ListCurationView: View { LazyVStack(spacing: 0) { Spacer() .frame(height: 20) - makeCurationCellList(curations) + makeCurationCellList(viewModel.curationList) Spacer() .frame(height: 32) @@ -55,23 +44,17 @@ struct ListCurationView: View { .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .navigationBarBackground ({ Color.shortcutsZipBackground }) .navigationBarTitleDisplayMode(.inline) - .navigationTitle(sectionTitle) - .onAppear { - curations = curationType.filterCuration(from: shortcutsZipViewModel) - } + .navigationTitle(viewModel.sectionTitle) } @ViewBuilder private func makeCurationCellList(_ curations: [Curation]) -> some View { ForEach(Array(curations.enumerated()), id: \.offset) { index, curation in - let data = NavigationReadCurationType(curation: curation, - navigationParentView: .curations) - UserCurationCell(curation: curation, lineLimit: 2, navigationParentView: .curations) - .navigationLinkRouter(data: data) + .navigationLinkRouter(data: curation) .listRowInsets(EdgeInsets()) .listRowSeparator(.hidden) .listRowBackground(Color.shortcutsZipBackground) diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift index adf759c0..291a764c 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift @@ -9,33 +9,24 @@ import SwiftUI struct ReadCurationView: View { @Environment(\.presentationMode) var presentation: Binding - - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @StateObject var writeCurationNavigation = WriteCurationNavigation() - - @State var authorInformation: User? = nil - @State var isWriting = false - @State var isTappedEditButton = false - @State var isTappedShareButton = false - @State var isTappedDeleteButton = false - @State var data: NavigationReadCurationType - @State var index = 0 + @StateObject var viewModel: ReadCurationViewModel var body: some View { ScrollView(showsIndicators: false) { - if data.isAdmin { + if viewModel.isAdmin { adminCuration } else { userCuration } VStack(spacing: 0) { - ForEach(shortcutsZipViewModel.userCurations[index].shortcuts, id: \.self) { shortcut in + ForEach($viewModel.curation.shortcuts, id: \.self) { shortcut in let data = NavigationReadShortcutType(shortcutID: shortcut.id, - navigationParentView: self.data.navigationParentView) - ShortcutCell(shortcutCell: shortcut, - navigationParentView: self.data.navigationParentView) + navigationParentView: .curations) + ShortcutCell(shortcutCell: shortcut.wrappedValue, + navigationParentView: .curations) .navigationLinkRouter(data: data) } @@ -48,20 +39,19 @@ struct ReadCurationView: View { .edgesIgnoringSafeArea(.top) .navigationBarTitleDisplayMode(.inline) .navigationBarItems(trailing: readCurationViewButtonByUser()) - .fullScreenCover(isPresented: $isWriting) { + .fullScreenCover(isPresented: $viewModel.isWriting) { NavigationRouter(content: editView, path: $writeCurationNavigation.navigationPath) .environmentObject(writeCurationNavigation) } - .alert(TextLiteral.readCurationViewDeletionTitle, isPresented: $isTappedDeleteButton) { + .alert(TextLiteral.readCurationViewDeletionTitle, isPresented: $viewModel.isTappedDeleteButton) { Button(role: .cancel) { - self.isTappedDeleteButton.toggle() + viewModel.isTappedDeleteButton.toggle() } label: { Text(TextLiteral.cancel) } Button(role: .destructive) { - shortcutsZipViewModel.deleteData(model: self.data.curation) - shortcutsZipViewModel.curationsMadeByUser = shortcutsZipViewModel.curationsMadeByUser.filter { $0.id != self.data.curation.id } + viewModel.deleteCuration() presentation.wrappedValue.dismiss() } label: { Text(TextLiteral.delete) @@ -77,10 +67,10 @@ struct ReadCurationView: View { StickyHeader(height: 100) VStack(spacing: 16) { - userInformation + UserNameCell(userInformation: viewModel.authInformation, gradeImage: viewModel.gradeImage) .padding(EdgeInsets(top: 103, leading: 16, bottom: 0, trailing: 16)) - UserCurationCell(curation: data.curation, navigationParentView: data.navigationParentView) + UserCurationCell(curation: viewModel.curation, navigationParentView: .curations) } } .padding(.bottom, 8) @@ -90,13 +80,13 @@ struct ReadCurationView: View { var adminCuration: some View { VStack { - StickyHeader(height: 304, image: data.curation.background) + StickyHeader(height: 304, image: viewModel.curation.background) .padding(.bottom, 20) HStack { VStack(alignment: .leading, spacing: 4) { - SubtitleTextView(text: data.curation.title) - Text(data.curation.subtitle.replacingOccurrences(of: "\\n", with: "\n")) + SubtitleTextView(text: viewModel.curation.title) + Text(viewModel.curation.subtitle.replacingOccurrences(of: "\\n", with: "\n")) .shortcutsZipBody2() .foregroundColor(.gray4) } @@ -106,20 +96,6 @@ struct ReadCurationView: View { .padding(.bottom, 8) } } - var userInformation: some View { - ZStack { - UserNameCell(userInformation: self.authorInformation, gradeImage: shortcutsZipViewModel.fetchShortcutGradeImage(isBig: false, shortcutGrade: shortcutsZipViewModel.checkShortcutGrade(userID: authorInformation?.id ?? "!"))) - } - .onAppear { - shortcutsZipViewModel.fetchUser(userID: self.data.curation.author, - isCurrentUser: false) { user in - authorInformation = user - } - if let index = shortcutsZipViewModel.userCurations.firstIndex(where: { $0.id == data.curation.id}) { - self.index = index - } - } - } } @@ -127,18 +103,18 @@ extension ReadCurationView { @ViewBuilder private func editView() -> some View { - WriteCurationSetView(isWriting: $isWriting, - curation: shortcutsZipViewModel.userCurations[index] - ,isEdit: true + WriteCurationSetView(isWriting: $viewModel.isWriting, + curation: $viewModel.curation, + isEdit: true ) .navigationDestination(for: WriteCurationInfoType.self) { data in - WriteCurationInfoView(data: data, isWriting: $isWriting) + WriteCurationInfoView(data: data, isWriting: $viewModel.isWriting) } } @ViewBuilder private func readCurationViewButtonByUser() -> some View { - if self.data.curation.author == shortcutsZipViewModel.currentUser() { + if viewModel.checkAuthor() { myCurationMenu } else { shareButton @@ -146,30 +122,30 @@ extension ReadCurationView { } private var myCurationMenu: some View { - Menu(content: { + Menu { Section { editButton shareButton deleteButton } - }, label: { + } label: { Image(systemName: "ellipsis") .foregroundColor(.gray4) - }) + } } private var editButton: some View { Button { - self.isWriting.toggle() + self.viewModel.isWriting.toggle() } label: { Label(TextLiteral.edit, systemImage: "square.and.pencil") } } private var shareButton: some View { - Button(action: { - shareCuration() - }) { + Button { + viewModel.shareCuration() + } label: { Label(TextLiteral.share, systemImage: "square.and.arrow.up") .foregroundColor(.gray4) .fontWeight(.medium) @@ -177,20 +153,10 @@ extension ReadCurationView { } private var deleteButton: some View { - Button(role: .destructive, action: { - isTappedDeleteButton.toggle() - }) { + Button(role: .destructive) { + viewModel.isTappedDeleteButton.toggle() + } label: { Label(TextLiteral.delete, systemImage: "trash.fill") } } - - private func shareCuration() { - guard let deepLink = URL(string: "ShortcutsZip://myPage/CurationDetailView?curationID=\(data.curation.id)") else { return } - - let activityVC = UIActivityViewController(activityItems: [deepLink], applicationActivities: nil) - let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene - guard let window = windowScene?.windows.first else { return } - window.rootViewController?.present(activityVC, animated: true, completion: nil) - } } - diff --git a/HappyAnding/HappyAnding/Views/HappyAndingApp.swift b/HappyAnding/HappyAnding/Views/HappyAndingApp.swift index b086a81b..918638ef 100644 --- a/HappyAnding/HappyAnding/Views/HappyAndingApp.swift +++ b/HappyAnding/HappyAnding/Views/HappyAndingApp.swift @@ -16,7 +16,7 @@ struct HappyAndingApp: App { @Environment(\.scenePhase) var scenePhase @Environment(\.openURL) private var openURL - @StateObject var shortcutsZipViewModel = ShortcutsZipViewModel() + @StateObject var shortcutsZipViewModel = ShortcutsZipViewModel.share @StateObject var loginAlerter = Alerter() @StateObject var gradeAlerter = Alerter() diff --git a/HappyAnding/HappyAnding/Views/ReadShortcutViews/ShowProfileView.swift b/HappyAnding/HappyAnding/Views/ReadShortcutViews/ShowProfileView.swift index 652b1a46..3fc3a211 100644 --- a/HappyAnding/HappyAnding/Views/ReadShortcutViews/ShowProfileView.swift +++ b/HappyAnding/HappyAnding/Views/ReadShortcutViews/ShowProfileView.swift @@ -165,12 +165,11 @@ extension ShowProfileView { VStack(spacing: 0) { ForEach(curations, id: \.self) { curation in - let data = NavigationReadCurationType(curation: curation, - navigationParentView: .shortcuts) + // TODO: navigation parent view 삭제 UserCurationCell(curation: curation, lineLimit: 2, - navigationParentView: data.navigationParentView) - .navigationLinkRouter(data: data) + navigationParentView: .curations) + .navigationLinkRouter(data: curation) } Spacer() diff --git a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift index f6750129..db91ece5 100644 --- a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift +++ b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift @@ -121,7 +121,7 @@ struct ShortcutTabView: View { @ViewBuilder private func secondTab() -> some View { - ExploreCurationView() + ExploreCurationView(viewModel: ExploreCurationViewModel()) .modifierNavigation() .navigationBarBackground ({ Color.shortcutsZipBackground }) .id(secondTabID) @@ -175,9 +175,7 @@ struct ShortcutTabView: View { isCurationDeeplink = true if let curation = shortcutsZipViewModel.fetchCurationDetail(curationID: tempCurationId) { - let data = NavigationReadCurationType(curation: curation, - navigationParentView: .myPage) - navigateLink(data: data) + navigateLink(data: curation) } } diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift index 54624019..0705abfe 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift @@ -16,12 +16,7 @@ struct WriteCurationSetView: View { @State var shortcutCells = [ShortcutCellModel]() @State var isSelected = false - @State var curation = Curation(title: "", - subtitle: "", - isAdmin: false, - background: "White", - author: "", - shortcuts: [ShortcutCellModel]()) + @Binding var curation: Curation @State var isTappedQuestionMark: Bool = false @State var deletedShortcutCells = [ShortcutCellModel]() @@ -123,9 +118,3 @@ struct WriteCurationSetView: View { .padding(.bottom, 20) } } - -struct WriteCurationSetView_Previews: PreviewProvider { - static var previews: some View { - WriteCurationSetView(isWriting: .constant(false), isEdit: false) - } -}