diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index e68c9c0a..f4168910 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -124,6 +124,7 @@ F94B435F2907B19A00987819 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = F94B435E2907B19A00987819 /* FirebaseAuth */; }; F94B43612907B19A00987819 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = F94B43602907B19A00987819 /* FirebaseFirestore */; }; F94B43632907B19A00987819 /* FirebaseFirestoreCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = F94B43622907B19A00987819 /* FirebaseFirestoreCombine-Community */; }; + F95F26542A45C89400B534EB /* WriteCurationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95F26532A45C89400B534EB /* WriteCurationViewModel.swift */; }; F96D45B72980301F000C2441 /* SubtitleTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45B62980301F000C2441 /* SubtitleTextView.swift */; }; F96D45BB29804057000C2441 /* EnvironmentValues+Alerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45BA29804057000C2441 /* EnvironmentValues+Alerter.swift */; }; F96D45BD29816578000C2441 /* StickyHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45BC29816578000C2441 /* StickyHeader.swift */; }; @@ -277,6 +278,7 @@ F91F09DC29AE012600E04FA0 /* ShortcutGrade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutGrade.swift; sourceTree = ""; }; F91F09DE29AE0B5E00E04FA0 /* GradeAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradeAlertView.swift; sourceTree = ""; }; F94B432D2907088400987819 /* UserCurationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCurationListView.swift; sourceTree = ""; }; + F95F26532A45C89400B534EB /* WriteCurationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteCurationViewModel.swift; sourceTree = ""; }; F96D45B62980301F000C2441 /* SubtitleTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleTextView.swift; sourceTree = ""; }; F96D45BA29804057000C2441 /* EnvironmentValues+Alerter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+Alerter.swift"; sourceTree = ""; }; F96D45BC29816578000C2441 /* StickyHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyHeader.swift; sourceTree = ""; }; @@ -596,6 +598,7 @@ A0F822AB2910B8F100AF4448 /* ShortcutsZipViewModel.swift */, 4D61A766291E1EE8000EF531 /* NavigationViewModel.swift */, F9AC2BB52935201C00165820 /* CheckUpdateVersion.swift */, + F95F26532A45C89400B534EB /* WriteCurationViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -863,6 +866,7 @@ 87E99CD929042536009B691F /* SectionType.swift in Sources */, 872A7D8F2918393B004A05B8 /* PrivacyPolicyView.swift in Sources */, A38115BA292B447D0043E8B8 /* ShortcutCardCell.swift in Sources */, + F95F26542A45C89400B534EB /* WriteCurationViewModel.swift in Sources */, 8792479B291BDF820040D5C3 /* SearchView.swift in Sources */, A3FF018E291ACFA500384211 /* WithdrawalView.swift in Sources */, 4D778A34290A53BA00C15AC4 /* UIApplication+Keyboard.swift in Sources */, diff --git a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift index 4e6df8e1..7b042c34 100644 --- a/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift +++ b/HappyAnding/HappyAnding/Extensions/View/View+Navigation.swift @@ -67,8 +67,8 @@ extension View { @ViewBuilder func getDestination(data: T, isPresented: Binding) -> some View { switch data { - case is WriteCurationInfoType: - WriteCurationInfoView(data: data as! WriteCurationInfoType, isWriting: isPresented) + case is WriteCurationViewModel: + WriteCurationInfoView(viewModel: data as! WriteCurationViewModel) default: EmptyView() } diff --git a/HappyAnding/HappyAnding/ViewModel/WriteCurationViewModel.swift b/HappyAnding/HappyAnding/ViewModel/WriteCurationViewModel.swift new file mode 100644 index 00000000..7c08911b --- /dev/null +++ b/HappyAnding/HappyAnding/ViewModel/WriteCurationViewModel.swift @@ -0,0 +1,67 @@ +// +// WriteCurationViewModel.swift +// HappyAnding +// +// Created by JeonJimin on 2023/06/23. +// + +import SwiftUI + +final class WriteCurationViewModel: ObservableObject, Hashable { + + static func == (lhs: WriteCurationViewModel, rhs: WriteCurationViewModel) -> Bool { + return false + } + func hash(into hasher: inout Hasher) { + hasher.combine(curation) + } + + private var shortcutsZipViewModel = ShortcutsZipViewModel.share + + //WriteCurationSet + @Published var isWriting = false + @Published var isEdit = false + + //좋아요 + 내가 작성한 단축어 목록 + @Published var shortcutCells = [ShortcutCellModel]() + //모음집 편집 시 전달받는 기존 모음집 정보 + @Published var curation = Curation(title: "", subtitle: "", isAdmin: false, background: "", author: "", shortcuts: [ShortcutCellModel]()) + + @Published var isTappedQuestionMark = false + //기존 선택 -> 편집 시 선택 해제 되어 기존 모음집 정보에서 삭제해야할 단축어 배열 + @Published var deletedShortcutCells = [ShortcutCellModel]() + + + //WriteCurationInfo + @Published var writeCurationNavigation = WriteCurationNavigation() + @Published var isValidTitle = false + @Published var isValidDescription = false + + var isIncomplete: Bool { + !(isValidTitle && isValidDescription) + } + + init() { + + } + + init(data: Curation) { + self.curation = data + } + + func fetchMakeCuration() { + shortcutCells = shortcutsZipViewModel.fetchShortcutMakeCuration().sorted { $0.title < $1.title } + if isEdit { + deletedShortcutCells = curation.shortcuts + } + } + + func addCuration() { + shortcutsZipViewModel.addCuration(curation: curation, isEdit: isEdit, deletedShortcutCells: deletedShortcutCells) + + self.isWriting.toggle() + if #available(iOS 16.1, *) { + writeCurationNavigation.navigationPath = .init() + } + } +} diff --git a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift index 936f4c45..e4d42119 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift @@ -78,12 +78,10 @@ struct UserCurationListView: View { @ViewBuilder private func writeCurationView() -> some View { - WriteCurationSetView(isWriting: $isWriting - , isEdit: false - ) - .navigationDestination(for: WriteCurationInfoType.self) { data in - WriteCurationInfoView(data: data, isWriting: $isWriting) - } + WriteCurationSetView(viewModel: WriteCurationViewModel()) + .navigationDestination(for: WriteCurationViewModel.self) { data in + WriteCurationInfoView(viewModel: data) + } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift index adf759c0..bd832e37 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadCurationView.swift @@ -127,12 +127,9 @@ extension ReadCurationView { @ViewBuilder private func editView() -> some View { - WriteCurationSetView(isWriting: $isWriting, - curation: shortcutsZipViewModel.userCurations[index] - ,isEdit: true - ) - .navigationDestination(for: WriteCurationInfoType.self) { data in - WriteCurationInfoView(data: data, isWriting: $isWriting) + WriteCurationSetView(viewModel: WriteCurationViewModel(data: data.curation)) + .navigationDestination(for: WriteCurationViewModel.self) { data in + WriteCurationInfoView(viewModel: data) } } diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift index 52a023ae..14b382ec 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift @@ -8,22 +8,10 @@ import SwiftUI struct WriteCurationInfoView: View { - - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @EnvironmentObject var writeCurationNavigation: WriteCurationNavigation + @StateObject var viewModel: WriteCurationViewModel @FocusState var isDescriptionFieldFocused: Bool - @State var data: WriteCurationInfoType - @Binding var isWriting: Bool - - @State var isValidTitle = false - @State var isValidDescription = false - - private var isIncomplete: Bool { - !(isValidTitle && isValidDescription) - } - var body: some View { VStack(spacing: 24) { ProgressView(value: 2, total: 2) @@ -34,8 +22,8 @@ struct WriteCurationInfoView: View { placeholder: TextLiteral.writeCurationInfoViewNamePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, - content: $data.curation.title, - isValid: $isValidTitle) + content: $viewModel.curation.title, + isValid: $viewModel.isValidTitle) .padding(.top, 12) .onSubmit { isDescriptionFieldFocused = true @@ -49,9 +37,8 @@ struct WriteCurationInfoView: View { lengthLimit: 40, isDownloadLinkTextField: false, inputHeight: 72, - content: Binding(get: {data.curation.subtitle}, - set: {data.curation.subtitle = $0}), - isValid: $isValidDescription) + content: $viewModel.curation.subtitle, + isValid: $viewModel.isValidDescription) .focused($isDescriptionFieldFocused) Spacer() @@ -60,23 +47,17 @@ struct WriteCurationInfoView: View { .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { - - shortcutsZipViewModel.addCuration(curation: data.curation, isEdit: data.isEdit, deletedShortcutCells: data.deletedShortcutCells) - - self.isWriting.toggle() - if #available(iOS 16.1, *) { - writeCurationNavigation.navigationPath = .init() - } + viewModel.addCuration() } label: { Text(TextLiteral.upload) .shortcutsZipHeadline() - .foregroundColor(isIncomplete ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) + .foregroundColor(viewModel.isIncomplete ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) } - .disabled(isIncomplete) + .disabled(viewModel.isIncomplete) } } .background(Color.shortcutsZipBackground) - .navigationBarTitle(data.isEdit ? TextLiteral.writeCurationInfoViewEdit : TextLiteral.wrietCurationInfoViewPost) + .navigationBarTitle(viewModel.isEdit ? TextLiteral.writeCurationInfoViewEdit : TextLiteral.wrietCurationInfoViewPost) .onAppear(perform : UIApplication.shared.hideKeyboard) } } diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift index 54624019..3da6d3ad 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift @@ -9,23 +9,7 @@ import SwiftUI struct WriteCurationSetView: View { - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @EnvironmentObject var writeCurationNavigation: WriteCurationNavigation - - @Binding var isWriting: Bool - - @State var shortcutCells = [ShortcutCellModel]() - @State var isSelected = false - @State var curation = Curation(title: "", - subtitle: "", - isAdmin: false, - background: "White", - author: "", - shortcuts: [ShortcutCellModel]()) - @State var isTappedQuestionMark: Bool = false - @State var deletedShortcutCells = [ShortcutCellModel]() - - let isEdit: Bool + @StateObject var viewModel: WriteCurationViewModel var body: some View { VStack { @@ -34,7 +18,7 @@ struct WriteCurationSetView: View { listHeader infomation - if shortcutCells.isEmpty { + if viewModel.shortcutCells.isEmpty { Spacer() Text(TextLiteral.writeCurationSetViewNoShortcuts) .shortcutsZipBody2() @@ -47,31 +31,28 @@ struct WriteCurationSetView: View { } } .background(Color.shortcutsZipBackground) - .navigationTitle(isEdit ? TextLiteral.writeCurationSetViewEdit : TextLiteral.writeCurationSetViewPost) + .navigationTitle(viewModel.isEdit ? TextLiteral.writeCurationSetViewEdit : TextLiteral.writeCurationSetViewPost) .navigationBarTitleDisplayMode(.inline) .onAppear { - self.shortcutCells = shortcutsZipViewModel.fetchShortcutMakeCuration().sorted { $0.title < $1.title } - if isEdit { - deletedShortcutCells = curation.shortcuts - } + viewModel.fetchMakeCuration() } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { - self.isWriting.toggle() + viewModel.isWriting.toggle() } label: { Text(TextLiteral.cancel) .shortcutsZipBody1() .foregroundColor(.gray4) } } - + ToolbarItem(placement: .navigationBarTrailing) { Text(TextLiteral.next) - .navigationLinkRouter(data: WriteCurationInfoType(curation: curation, deletedShortcutCells: deletedShortcutCells, isEdit: isEdit), isPresented: $isWriting) + .navigationLinkRouter(data: viewModel, isPresented: $viewModel.isWriting) .shortcutsZipHeadline() - .foregroundColor(curation.shortcuts.isEmpty ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) - .disabled(curation.shortcuts.isEmpty) + .foregroundColor(viewModel.curation.shortcuts.isEmpty ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) + .disabled(viewModel.curation.shortcuts.isEmpty) } } } @@ -86,7 +67,7 @@ struct WriteCurationSetView: View { .shortcutsZipFootnote() .foregroundColor(.gray3) Spacer() - Text("\(curation.shortcuts.count)개") + Text("\(viewModel.curation.shortcuts.count)개") .shortcutsZipBody2() .foregroundColor(.shortcutsZipPrimary) } @@ -97,11 +78,11 @@ struct WriteCurationSetView: View { var shortcutList: some View { ScrollView { - ForEach(Array(shortcutCells)) { shortcut in + ForEach(Array(viewModel.shortcutCells)) { shortcut in CheckBoxShortcutCell( - selectedShortcutCells: $curation.shortcuts, isShortcutTapped: curation.shortcuts.contains(shortcut), - shortcutCell: shortcut - ) + selectedShortcutCells: $viewModel.curation.shortcuts, + isShortcutTapped: $viewModel.curation.shortcuts.contains{$0.id == shortcut.id}, + shortcutCell: shortcut) } } .frame(maxWidth: .infinity) @@ -123,9 +104,3 @@ struct WriteCurationSetView: View { .padding(.bottom, 20) } } - -struct WriteCurationSetView_Previews: PreviewProvider { - static var previews: some View { - WriteCurationSetView(isWriting: .constant(false), isEdit: false) - } -}