From c5ca57b32366829a2218862f19300c6a635cf729 Mon Sep 17 00:00:00 2001 From: jeonjimin Date: Wed, 21 Jun 2023 01:30:18 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=20#122=20-=20bottom=20sheet=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Halmap.xcodeproj/project.pbxproj | 16 +++-- .../NCAlbum.imageset/Contents.json" | 2 +- Halmap/Extensions/CustomCorner.swift | 17 ++++++ .../HalfModalPresentationController.swift | 36 +++++++++++ Halmap/View/HalfSheetView.swift | 60 ++++++++++--------- Halmap/View/ScalingHeaderView.swift | 24 ++++++-- 6 files changed, 117 insertions(+), 38 deletions(-) create mode 100644 Halmap/Extensions/CustomCorner.swift create mode 100644 Halmap/View/HalfModalPresentationController.swift diff --git a/Halmap.xcodeproj/project.pbxproj b/Halmap.xcodeproj/project.pbxproj index 2b31e5b..af8e7ad 100644 --- a/Halmap.xcodeproj/project.pbxproj +++ b/Halmap.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 87F6ECF1291677AC004533C4 /* Halmap+UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87F6ECF0291677AC004533C4 /* Halmap+UIApplication.swift */; }; 87F6ECF52916B331004533C4 /* Halmap+UINavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87F6ECF42916B331004533C4 /* Halmap+UINavigationController.swift */; }; 87F6ECF72916BB44004533C4 /* Halmap+UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87F6ECF62916BB44004533C4 /* Halmap+UIView.swift */; }; - A813C77429C779C400CF73FE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A813C77329C779C400CF73FE /* GoogleService-Info.plist */; }; A81FFC7A28F15D9900B0FC7C /* HalmapApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81FFC7928F15D9900B0FC7C /* HalmapApp.swift */; }; A81FFC7C28F15D9900B0FC7C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81FFC7B28F15D9900B0FC7C /* ContentView.swift */; }; A81FFC7E28F15D9C00B0FC7C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A81FFC7D28F15D9C00B0FC7C /* Assets.xcassets */; }; @@ -43,6 +42,7 @@ F939EBBC29D5920F005ED8CA /* OffsetModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F939EBBB29D5920F005ED8CA /* OffsetModifier.swift */; }; F949284F28F2AFB800901F27 /* Music.json in Resources */ = {isa = PBXBuildFile; fileRef = F949284E28F2AFB800901F27 /* Music.json */; }; F95CE98B2917A8EF00FFE213 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = F95CE98A2917A8EF00FFE213 /* Settings.bundle */; }; + F95EF67C2A40695C00C6C3E7 /* HalfModalPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95EF67B2A40695C00C6C3E7 /* HalfModalPresentationController.swift */; }; F98F622929B4C9BD0025F50E /* Themes.swift in Sources */ = {isa = PBXBuildFile; fileRef = F98F622829B4C9BD0025F50E /* Themes.swift */; }; F98F622B29B4CB450025F50E /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F98F622A29B4CB450025F50E /* ThemeManager.swift */; }; F98F623129B59CE60025F50E /* TeamName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F98F623029B59CE60025F50E /* TeamName.swift */; }; @@ -50,10 +50,12 @@ F9A178222A1BF5CB003E8E4C /* HalfSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9A178212A1BF5CB003E8E4C /* HalfSheetView.swift */; }; F9A178262A1C8B01003E8E4C /* PlayListFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9A178252A1C8B01003E8E4C /* PlayListFilter.swift */; }; F9A2DAA62A07DE9A008B84A9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F9A2DAA52A07DE9A008B84A9 /* Preview Assets.xcassets */; }; + F9A96B782A4060E200DD42B5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F9A96B772A4060E200DD42B5 /* GoogleService-Info.plist */; }; F9B3B7B529B7397600232BB8 /* MapName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9B3B7B429B7397600232BB8 /* MapName.swift */; }; F9B3B7B729B842DD00232BB8 /* SongDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9B3B7B629B842DD00232BB8 /* SongDetailView.swift */; }; F9B95BB928F271A100728048 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9B95BB828F271A100728048 /* DataManager.swift */; }; F9B95BBB28F271B800728048 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9B95BBA28F271B800728048 /* Model.swift */; }; + F9DAABB02A4190A4001168A9 /* CustomCorner.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9DAABAF2A4190A4001168A9 /* CustomCorner.swift */; }; F9E4642329E8089A009E12FC /* ScalingHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E4642229E8089A009E12FC /* ScalingHeaderView.swift */; }; F9EB19C129168E45002DFE46 /* Song.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9EB19BD29168336002DFE46 /* Song.swift */; }; /* End PBXBuildFile section */ @@ -63,7 +65,6 @@ 87F6ECF0291677AC004533C4 /* Halmap+UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Halmap+UIApplication.swift"; sourceTree = ""; }; 87F6ECF42916B331004533C4 /* Halmap+UINavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Halmap+UINavigationController.swift"; sourceTree = ""; }; 87F6ECF62916BB44004533C4 /* Halmap+UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Halmap+UIView.swift"; sourceTree = ""; }; - A813C77329C779C400CF73FE /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; A81FFC7628F15D9900B0FC7C /* Halmap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Halmap.app; sourceTree = BUILT_PRODUCTS_DIR; }; A81FFC7928F15D9900B0FC7C /* HalmapApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HalmapApp.swift; sourceTree = ""; }; A81FFC7B28F15D9900B0FC7C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -93,6 +94,7 @@ F939EBBB29D5920F005ED8CA /* OffsetModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OffsetModifier.swift; sourceTree = ""; }; F949284E28F2AFB800901F27 /* Music.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Music.json; sourceTree = ""; }; F95CE98A2917A8EF00FFE213 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; + F95EF67B2A40695C00C6C3E7 /* HalfModalPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HalfModalPresentationController.swift; sourceTree = ""; }; F98F622829B4C9BD0025F50E /* Themes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Themes.swift; sourceTree = ""; }; F98F622A29B4CB450025F50E /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = ""; }; F98F623029B59CE60025F50E /* TeamName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamName.swift; sourceTree = ""; }; @@ -100,10 +102,12 @@ F9A178212A1BF5CB003E8E4C /* HalfSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HalfSheetView.swift; sourceTree = ""; }; F9A178252A1C8B01003E8E4C /* PlayListFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayListFilter.swift; sourceTree = ""; }; F9A2DAA52A07DE9A008B84A9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + F9A96B772A4060E200DD42B5 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; F9B3B7B429B7397600232BB8 /* MapName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapName.swift; sourceTree = ""; }; F9B3B7B629B842DD00232BB8 /* SongDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SongDetailView.swift; sourceTree = ""; }; F9B95BB828F271A100728048 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; F9B95BBA28F271B800728048 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; }; + F9DAABAF2A4190A4001168A9 /* CustomCorner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCorner.swift; sourceTree = ""; }; F9E4642229E8089A009E12FC /* ScalingHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalingHeaderView.swift; sourceTree = ""; }; F9EB19BD29168336002DFE46 /* Song.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Song.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -126,7 +130,7 @@ A81FFC6D28F15D9900B0FC7C = { isa = PBXGroup; children = ( - A813C77329C779C400CF73FE /* GoogleService-Info.plist */, + F9A96B772A4060E200DD42B5 /* GoogleService-Info.plist */, B2699E0E28F1CB8800267A4F /* Font */, A81FFC7828F15D9900B0FC7C /* Halmap */, A81FFC7728F15D9900B0FC7C /* Products */, @@ -187,6 +191,7 @@ F939EBB929D58FB2005ED8CA /* StorageContentView.swift */, F939EBBB29D5920F005ED8CA /* OffsetModifier.swift */, F98F8D5C29D85B0C00F9C956 /* RequestSongView.swift */, + F95EF67B2A40695C00C6C3E7 /* HalfModalPresentationController.swift */, ); path = View; sourceTree = ""; @@ -218,6 +223,7 @@ 87F6ECF0291677AC004533C4 /* Halmap+UIApplication.swift */, 87F6ECF42916B331004533C4 /* Halmap+UINavigationController.swift */, 87F6ECF62916BB44004533C4 /* Halmap+UIView.swift */, + F9DAABAF2A4190A4001168A9 /* CustomCorner.swift */, ); path = Extensions; sourceTree = ""; @@ -342,7 +348,7 @@ files = ( F95CE98B2917A8EF00FFE213 /* Settings.bundle in Resources */, F9A2DAA62A07DE9A008B84A9 /* Preview Assets.xcassets in Resources */, - A813C77429C779C400CF73FE /* GoogleService-Info.plist in Resources */, + F9A96B782A4060E200DD42B5 /* GoogleService-Info.plist in Resources */, A81FFC8128F15D9C00B0FC7C /* Preview Assets.xcassets in Resources */, B2699E0D28F1CB7E00267A4F /* Pretendard-Bold.otf in Resources */, A81FFC7E28F15D9C00B0FC7C /* Assets.xcassets in Resources */, @@ -372,6 +378,7 @@ F98F8D5D29D85B0C00F9C956 /* RequestSongView.swift in Sources */, A81FFC7C28F15D9900B0FC7C /* ContentView.swift in Sources */, A81FFC9D28F180A000B0FC7C /* SongPlayerView.swift in Sources */, + F95EF67C2A40695C00C6C3E7 /* HalfModalPresentationController.swift in Sources */, A81FFC8628F15D9C00B0FC7C /* Halmap.xcdatamodeld in Sources */, 87F6ECF72916BB44004533C4 /* Halmap+UIView.swift in Sources */, F91BE5FB29B18AF800F7E488 /* MainTabView.swift in Sources */, @@ -385,6 +392,7 @@ A81FFCA728F1B84A00B0FC7C /* Halmap+Color.swift in Sources */, F98F622929B4C9BD0025F50E /* Themes.swift in Sources */, 20317FB228F2CCBB00A30E09 /* TeamChangingView.swift in Sources */, + F9DAABB02A4190A4001168A9 /* CustomCorner.swift in Sources */, A81FFC7A28F15D9900B0FC7C /* HalmapApp.swift in Sources */, F91BE5FD29B18D1E00F7E488 /* MainSongListTabView.swift in Sources */, F939EBBA29D58FB2005ED8CA /* StorageContentView.swift in Sources */, diff --git "a/Halmap/Assets.xcassets/\355\214\200 \354\225\250\353\262\224 \354\273\244\353\262\204/NCAlbum.imageset/Contents.json" "b/Halmap/Assets.xcassets/\355\214\200 \354\225\250\353\262\224 \354\273\244\353\262\204/NCAlbum.imageset/Contents.json" index a0647a8..afd4eba 100644 --- "a/Halmap/Assets.xcassets/\355\214\200 \354\225\250\353\262\224 \354\273\244\353\262\204/NCAlbum.imageset/Contents.json" +++ "b/Halmap/Assets.xcassets/\355\214\200 \354\225\250\353\262\224 \354\273\244\353\262\204/NCAlbum.imageset/Contents.json" @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "NcAlbum.png", + "filename" : "NCAlbum.png", "idiom" : "universal", "scale" : "1x" }, diff --git a/Halmap/Extensions/CustomCorner.swift b/Halmap/Extensions/CustomCorner.swift new file mode 100644 index 0000000..301a339 --- /dev/null +++ b/Halmap/Extensions/CustomCorner.swift @@ -0,0 +1,17 @@ +// +// CustomCorner.swift +// Halmap +// +// Created by JeonJimin on 2023/06/20. +// + +import SwiftUI + +struct CustomCorner: Shape { + var corners: UIRectCorner + func path(in rect: CGRect) -> Path { + let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: 35, height: 35)) + + return Path(path.cgPath) + } +} diff --git a/Halmap/View/HalfModalPresentationController.swift b/Halmap/View/HalfModalPresentationController.swift new file mode 100644 index 0000000..ae80719 --- /dev/null +++ b/Halmap/View/HalfModalPresentationController.swift @@ -0,0 +1,36 @@ +// +// HalfModalPresentationController.swift +// Halmap +// +// Created by JeonJimin on 2023/06/19. +// + +import SwiftUI + +class HalfSheetController: UIHostingController where Content : View { + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + if let presentation = sheetPresentationController { + presentation.detents = [.medium()] + presentation.prefersGrabberVisible = true + presentation.largestUndimmedDetentIdentifier = .none + } + } +} + +struct HalfSheet: UIViewControllerRepresentable where Content : View { + + private let content: Content + + @inlinable init(@ViewBuilder content: () -> Content) { + self.content = content() + } + + func makeUIViewController(context: Context) -> HalfSheetController { + return HalfSheetController(rootView: content) + } + + func updateUIViewController(_: HalfSheetController, context: Context) { + } +} diff --git a/Halmap/View/HalfSheetView.swift b/Halmap/View/HalfSheetView.swift index 557138c..01244f5 100644 --- a/Halmap/View/HalfSheetView.swift +++ b/Halmap/View/HalfSheetView.swift @@ -10,40 +10,44 @@ import SwiftUI struct HalfSheetView: View { @Environment(\.managedObjectContext) var managedObjectContext let persistence = PersistenceController.shared - @ObservedObject var collectedSong: CollectedSong - @State var songData: Song - @State var song: CollectedSong = CollectedSong() - var team: String + @Binding var showSheet: Bool + @Binding var collectedSongData: CollectedSong? + var body: some View { VStack(spacing: 0) { - HStack(spacing: 16) { - Image("\(team)SongListImage") - .frame(width: 52, height: 52) - .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4) - VStack(alignment: .leading, spacing: 6) { - Text(songData.title ) - .font(Font.Halmap.CustomBodyBold) - .foregroundColor(.customBlack) - Text(TeamName(rawValue: team )?.fetchTeamNameKr() ?? ".") - .font(Font.Halmap.CustomCaptionMedium) - .foregroundColor(.customDarkGray) + // Capsule() + // .fill(Color.gray) + // .frame(width: 35, height: 5) + // .padding(.vertical, 18) + if let collectedSongData { + HStack(spacing: 16) { + Image(collectedSongData.type ? "\(collectedSongData.team ?? "")Album" : "\(collectedSongData.team ?? "")Player") + .resizable() + .frame(width: 52, height: 52) + .cornerRadius(10) + .shadow(color: .black.opacity(0.25), radius: 4, x: 0, y: 4) + VStack(alignment: .leading, spacing: 6) { + Text(collectedSongData.title ?? "") + .font(Font.Halmap.CustomBodyBold) + .foregroundColor(.customBlack) + Text(TeamName(rawValue: collectedSongData.team ?? "" )?.fetchTeamNameKr() ?? ".") + .font(Font.Halmap.CustomCaptionMedium) + .foregroundColor(.customDarkGray) + } + .frame(maxWidth: .infinity, alignment: .leading) } - .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 20) + .padding(.top, 27) + Divider() + .overlay(Color.customGray.opacity(0.6)) + .padding(EdgeInsets(top: 20, leading: 0, bottom: 29, trailing: 0)) + MenuItem(menuType: .cancelLiked, collectedSong: collectedSongData, showSheet: $showSheet) + MenuItem(menuType: .playNext, collectedSong: collectedSongData, showSheet: $showSheet) + MenuItem(menuType: .playLast, collectedSong: collectedSongData, showSheet: $showSheet) + Spacer() } - .padding(.horizontal, 20) - .padding(.top, 27) - Divider() - .overlay(Color.customGray.opacity(0.6)) - .padding(EdgeInsets(top: 20, leading: 0, bottom: 29, trailing: 0)) - MenuItem(menuType: .cancelLiked, collectedSong: collectedSong, showSheet: $showSheet) - MenuItem(menuType: .playNext, collectedSong: collectedSong, showSheet: $showSheet) - MenuItem(menuType: .playLast, collectedSong: collectedSong, showSheet: $showSheet) - Spacer() - } - .onAppear() { - print("****\(songData)") } } } diff --git a/Halmap/View/ScalingHeaderView.swift b/Halmap/View/ScalingHeaderView.swift index e7ba822..d1adb5c 100644 --- a/Halmap/View/ScalingHeaderView.swift +++ b/Halmap/View/ScalingHeaderView.swift @@ -13,8 +13,11 @@ struct ScalingHeaderView: View { var topEdge: CGFloat @State var offset: CGFloat = 0 + @State var isShowSheet = false + @State var collectedSongData: CollectedSong? @FetchRequest(entity: CollectedSong.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \CollectedSong.date, ascending: true)], predicate: PlayListFilter(filter: "favorite").predicate, animation: .default) private var collectedSongs: FetchedResults + let persistence = PersistenceController.shared var body: some View { @@ -55,8 +58,8 @@ struct ScalingHeaderView: View { .frame(width: 200, height: 200) .padding(.top, 60) } else { - ForEach(collectedSongs) { favoriteSong in - let song = Song( + ForEach(self.collectedSongs, id: \.self) { favoriteSong in + var song = Song( id: favoriteSong.id ?? "", type: favoriteSong.type , title: favoriteSong.title ?? "" , @@ -95,10 +98,21 @@ struct ScalingHeaderView: View { .lineLimit(1) Button { - persistence.deleteSongs(song: favoriteSong) + print("scaling favorite",favoriteSong) + self.collectedSongData = favoriteSong + + song = Song(id: favoriteSong.id ?? "", type: favoriteSong.type, title: favoriteSong.title ?? "", lyrics: favoriteSong.lyrics ?? "", info: favoriteSong.info ?? "", url: favoriteSong.url ?? "") + + isShowSheet.toggle() + } label: { - Image(systemName: "heart.fill") - .foregroundColor(.mainGreen) + Image(systemName: "ellipsis") + .foregroundColor(.black.opacity(0.2)) + } + .sheet(isPresented: $isShowSheet) { + HalfSheet { + HalfSheetView(showSheet: $isShowSheet, collectedSongData: $collectedSongData) + } } } .padding(.horizontal, 20)