From 48057b29d49afdefa09043970d7356b456bd0061 Mon Sep 17 00:00:00 2001 From: exsky Date: Wed, 19 Oct 2022 16:33:09 +0800 Subject: [PATCH] :sparkles: feat: delete button for secret location voew --- BaoAnGongFisher.xcodeproj/project.pbxproj | 8 +++ BaoAnGongFisher/Location/AddPinAlert.swift | 16 +++-- BaoAnGongFisher/Location/DelPinAlert.swift | 68 +++++++++++++++++++ .../Location/FishingLocationView.swift | 25 ++++++- .../Location/SecretLocationsDataLoader.swift | 20 +++--- BaoAnGongFisher/MainListView.swift | 1 + .../StampAlbum/AddStampAlert.swift | 39 +++++++++++ .../StampAlbum/StampAlbumView.swift | 2 +- 8 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 BaoAnGongFisher/Location/DelPinAlert.swift create mode 100644 BaoAnGongFisher/StampAlbum/AddStampAlert.swift diff --git a/BaoAnGongFisher.xcodeproj/project.pbxproj b/BaoAnGongFisher.xcodeproj/project.pbxproj index 349e06a..ec1dfa7 100644 --- a/BaoAnGongFisher.xcodeproj/project.pbxproj +++ b/BaoAnGongFisher.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 728A39E059B92D90C00B8B85 /* awsconfiguration.json in Resources */ = {isa = PBXBuildFile; fileRef = 1209FED1B8FACAAD71D4D963 /* awsconfiguration.json */; }; 85A8B805D195745AFCEBA97D /* Pods_BaoAnGongFisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDBF69B71642DA6D691A6B31 /* Pods_BaoAnGongFisher.framework */; }; C02A155828FE5869002C3F01 /* MySecretLocations.json in Resources */ = {isa = PBXBuildFile; fileRef = C02A155728FE5869002C3F01 /* MySecretLocations.json */; }; + C02A155A28FE8AE2002C3F01 /* AddStampAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C02A155928FE8AE2002C3F01 /* AddStampAlert.swift */; }; + C02A155C28FE95CB002C3F01 /* DelPinAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C02A155B28FE95CB002C3F01 /* DelPinAlert.swift */; }; C03C80FC28EB4AB400CD3719 /* AWSAPIPlugin in Frameworks */ = {isa = PBXBuildFile; productRef = C03C80FB28EB4AB400CD3719 /* AWSAPIPlugin */; }; C03C80FE28EB4AB400CD3719 /* AWSCognitoAuthPlugin in Frameworks */ = {isa = PBXBuildFile; productRef = C03C80FD28EB4AB400CD3719 /* AWSCognitoAuthPlugin */; }; C03C810028EB4AB400CD3719 /* AWSDataStorePlugin in Frameworks */ = {isa = PBXBuildFile; productRef = C03C80FF28EB4AB400CD3719 /* AWSDataStorePlugin */; }; @@ -76,6 +78,8 @@ A8F2B2BA875308AF2AEB85DD /* Pods-BaoAnGongFisher-BaoAnGongFisherUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BaoAnGongFisher-BaoAnGongFisherUITests.debug.xcconfig"; path = "Target Support Files/Pods-BaoAnGongFisher-BaoAnGongFisherUITests/Pods-BaoAnGongFisher-BaoAnGongFisherUITests.debug.xcconfig"; sourceTree = ""; }; A922BFD5177E71D109625352 /* MemberLevelEnum.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = MemberLevelEnum.swift; path = amplify/generated/models/MemberLevelEnum.swift; sourceTree = ""; }; C02A155728FE5869002C3F01 /* MySecretLocations.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MySecretLocations.json; sourceTree = ""; }; + C02A155928FE8AE2002C3F01 /* AddStampAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddStampAlert.swift; sourceTree = ""; }; + C02A155B28FE95CB002C3F01 /* DelPinAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelPinAlert.swift; sourceTree = ""; }; C04029D928C84E5900F83CD9 /* BaoAnGongFisher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BaoAnGongFisher.app; sourceTree = BUILT_PRODUCTS_DIR; }; C04029DC28C84E5900F83CD9 /* BaoAnGongFisherApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaoAnGongFisherApp.swift; sourceTree = ""; }; C04029DE28C84E5900F83CD9 /* ToxicFishListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToxicFishListView.swift; sourceTree = ""; }; @@ -231,6 +235,7 @@ C0C3BBDA28DCACF000721EB9 /* AddPinAlert.swift */, C0C3BBD828D9EAAF00721EB9 /* SecretLocation.swift */, C0A8F3B828DF558400CDCFE2 /* SecretLocationsDataLoader.swift */, + C02A155B28FE95CB002C3F01 /* DelPinAlert.swift */, ); path = Location; sourceTree = ""; @@ -239,6 +244,7 @@ isa = PBXGroup; children = ( C0619BEB28F251A5007E9569 /* StampAlbumView.swift */, + C02A155928FE8AE2002C3F01 /* AddStampAlert.swift */, ); path = StampAlbum; sourceTree = ""; @@ -544,12 +550,14 @@ C0FFBFE928CAC5FC00E2202C /* ToxicFish.swift in Sources */, C04029DF28C84E5900F83CD9 /* ToxicFishListView.swift in Sources */, C0C3BBDB28DCACF100721EB9 /* AddPinAlert.swift in Sources */, + C02A155A28FE8AE2002C3F01 /* AddStampAlert.swift in Sources */, C0A4FC5228D212AA00DACE2E /* FishingLocationView.swift in Sources */, C0C3BBD928D9EAB000721EB9 /* SecretLocation.swift in Sources */, C0619BF028F25F58007E9569 /* MainListView.swift in Sources */, C0A8F3B928DF558400CDCFE2 /* SecretLocationsDataLoader.swift in Sources */, C04029DD28C84E5900F83CD9 /* BaoAnGongFisherApp.swift in Sources */, 476B86A75FD7FF3185D6BD82 /* MemberLevelEnum.swift in Sources */, + C02A155C28FE95CB002C3F01 /* DelPinAlert.swift in Sources */, D3F515E42F7741D388700C29 /* User+Schema.swift in Sources */, 6E758E1D6ABB71ABBE37C90A /* User.swift in Sources */, 59B4F045D29A020C08FAB73C /* AmplifyModels.swift in Sources */, diff --git a/BaoAnGongFisher/Location/AddPinAlert.swift b/BaoAnGongFisher/Location/AddPinAlert.swift index 0e75992..f41699e 100644 --- a/BaoAnGongFisher/Location/AddPinAlert.swift +++ b/BaoAnGongFisher/Location/AddPinAlert.swift @@ -16,13 +16,15 @@ struct AddPinAlert: View { @Binding var myLocationName: String @Binding var currentRegion: MKCoordinateRegion // @Binding var pinsData: [PinLocation] - @Binding var locationLoader: LocationsLoader + @Binding var locationLoader: LocationLoader @State var myLocationRank: Int = 3 - var boxTitle: String = "在十字記號下新增私房釣點?" + var boxTitle: String = "新增私房釣點?" var body: some View { VStack { Text(boxTitle) + .font(.title2) + .fontWeight(.semibold) TextField("自訂名稱", text: $myLocationName) .textFieldStyle(RoundedBorderTextFieldStyle()) Picker("", selection: $myLocationRank) { @@ -57,7 +59,10 @@ struct AddPinAlert: View { .offset(y: alertIsPresented ? screenSize.height * 0.2 : screenSize.height) } - // TODO: save the new data in file + // To create new location + // 1. new location from cross, and append its info into locationData array + // 2. save whole locaionData to file + // 3. reload the pins to view from file func saveLocation() { //self.pinsData.append( self.locationLoader.locationData.append( @@ -66,8 +71,7 @@ struct AddPinAlert: View { longitude: currentRegion.center.longitude), rank: myLocationRank) ) - locationLoader.saveDataToFile() - locationLoader.loadDataFromFile() + self.locationLoader.saveAndReloadLocation() } } @@ -80,7 +84,7 @@ struct AddPinAlert_Previews: PreviewProvider { center: CLLocationCoordinate2D(latitude: 25.144274, longitude: 121.381837), span: MKCoordinateSpan(latitudeDelta: 0.08, longitudeDelta: 0.08)) ), - locationLoader: .constant(LocationsLoader()) + locationLoader: .constant(LocationLoader()) // pinsData: .constant(SecretLocationsData) ) } diff --git a/BaoAnGongFisher/Location/DelPinAlert.swift b/BaoAnGongFisher/Location/DelPinAlert.swift new file mode 100644 index 0000000..af9cbae --- /dev/null +++ b/BaoAnGongFisher/Location/DelPinAlert.swift @@ -0,0 +1,68 @@ +// +// DelPinAlert.swift +// BaoAnGongFisher +// +// Created by nipapa on 2022/10/18. +// + +import SwiftUI + +struct DelPinAlert: View { + + let screenSize = UIScreen.main.bounds + @Binding var alertIsPresented: Bool + @Binding var locationLoader: LocationLoader + var boxTitle: String = "刪除釣點" + + var body: some View { + VStack { + Text(boxTitle) + .font(.title2) + .fontWeight(.semibold) + ScrollView(.vertical) { + LazyVStack { + ForEach(Array(self.locationLoader.encodeCoordinate().enumerated()), id: \.element) { index, item in + HStack { + Text(item.name) + .frame(alignment: .leading) + .font(.headline) + Spacer() + Button { + delSingleLocation(pin: item, index: index) + } label: { + Label("", systemImage: "xmark.bin.circle") + .labelStyle(.iconOnly) + .frame(width: 20, height:20) + .foregroundColor(.white) + .cornerRadius(5) + .padding(10) + } + } + } + } + } + } + .padding() + .frame(width: screenSize.width * 0.6, height: screenSize.height * 0.4) + .background(Color.indigo) + .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous)) + .shadow(color: Color.gray, radius: 15, x: -1, y: -1) + .offset(y: alertIsPresented ? screenSize.height * 0.1 : screenSize.height) + } + + func delSingleLocation(pin: FishPinAnnotation, index: Int) { + //func delSingleLocation(at indexSet: IndexSet) { + self.locationLoader.locationData.remove(at: index) + self.locationLoader.saveAndReloadLocation() + self.alertIsPresented.toggle() + } +} + +struct DelPinAlert_Previews: PreviewProvider { + static var previews: some View { + DelPinAlert(alertIsPresented: .constant(false), + locationLoader: .constant(LocationLoader()) + ) + } +} + diff --git a/BaoAnGongFisher/Location/FishingLocationView.swift b/BaoAnGongFisher/Location/FishingLocationView.swift index 921985d..e320c1f 100644 --- a/BaoAnGongFisher/Location/FishingLocationView.swift +++ b/BaoAnGongFisher/Location/FishingLocationView.swift @@ -25,9 +25,10 @@ struct MapView: View { // 用來記錄長按手勢是否被觸發 @State private var isLongPressed = false @StateObject private var viewModel = FishingLocationModel() - @State private var myLocationLoader = LocationsLoader() + @State private var myLocationLoader = LocationLoader() @State private var customLocation = ScreenLocation(latitude: 0, longitude: 0) @State private var addLocationAlertIsPresented: Bool = false + @State private var delLocationListIsPresented: Bool = false @State private var newSecretLocationName: String = "私房釣點" @State private var storeNewLocation: Bool = false @@ -89,7 +90,7 @@ struct MapView: View { .symbolVariant(.fill) .padding(10) } - HStack { + HStack { // 新增釣點 Spacer() Button(action: newSecretLocation) { Label("", systemImage: "plus.rectangle.on.folder.fill") @@ -101,6 +102,18 @@ struct MapView: View { .padding(10) } } + HStack { // 刪除釣點 + Spacer() + Button(action: delSecretLocation) { + Label("", systemImage: "bin.xmark.fill") + .labelStyle(.iconOnly) + .frame(width: 40, height:40) + .foregroundColor(.white) + .background(Color.red) + .cornerRadius(15) + .padding(10) + } + } Spacer() } VStack(alignment: .center) { @@ -112,11 +125,17 @@ struct MapView: View { currentRegion: $viewModel.region, locationLoader: $myLocationLoader) //pinsData: $myLocationLoader.locationData) + DelPinAlert(alertIsPresented: $delLocationListIsPresented, + locationLoader: $myLocationLoader) } } func newSecretLocation() { - self.addLocationAlertIsPresented = true + self.addLocationAlertIsPresented.toggle() + } + + func delSecretLocation() { + self.delLocationListIsPresented.toggle() } } diff --git a/BaoAnGongFisher/Location/SecretLocationsDataLoader.swift b/BaoAnGongFisher/Location/SecretLocationsDataLoader.swift index 616b936..f4d4e2e 100644 --- a/BaoAnGongFisher/Location/SecretLocationsDataLoader.swift +++ b/BaoAnGongFisher/Location/SecretLocationsDataLoader.swift @@ -8,7 +8,7 @@ import Foundation import CoreLocation -public class LocationsLoader { +public class LocationLoader { @Published var originLoadData = [FishPinAnnotation]() @Published var locationData = [PinLocation]() @@ -51,6 +51,8 @@ public class LocationsLoader { } } + // 將 FishPinAnnotation 轉換後加入 locationData + // 為了讀入檔案所製作 func transferCoordinate() { // 將目前程式使用中的圖釘清單內新增轉換後的資料 for pin in self.originLoadData { self.locationData.append( @@ -63,6 +65,8 @@ public class LocationsLoader { } } + // 以 locationData 生成新的 [FishPinAnnotation] + // 這是為了提供給寫檔案時使用 func encodeCoordinate() -> [FishPinAnnotation] { var retPins: [FishPinAnnotation] = [] for pin in self.locationData { @@ -108,15 +112,6 @@ public class LocationsLoader { } catch { print(error) } -// //-- -// guard let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first else { -// return -// } -// let savedFolderUrl = url.appendingPathComponent("saved") -// //let fileUrl = savedFolderUrl.appendingPathComponent("NewSecretLocations.json") -// if manager.fileExists(atPath: fileUrl.absoluteString) { // 先前存檔過,就從存檔紀錄讀資料 -// print("Save File > exist!!") -// } // -- } func copyFileFromBundleToDocumentsFolder(sourceFile: String, destinationFile: String = "") { @@ -147,6 +142,11 @@ public class LocationsLoader { func getLocations () -> [PinLocation] { return self.locationData } + + func saveAndReloadLocation() { + self.saveDataToFile() + self.loadDataFromFile() + } } struct FishPinAnnotation: Hashable, Codable{ diff --git a/BaoAnGongFisher/MainListView.swift b/BaoAnGongFisher/MainListView.swift index c012938..14197a7 100644 --- a/BaoAnGongFisher/MainListView.swift +++ b/BaoAnGongFisher/MainListView.swift @@ -27,6 +27,7 @@ struct MainListView: View { Text("私藏釣點") } } + .accentColor(.pink) } } diff --git a/BaoAnGongFisher/StampAlbum/AddStampAlert.swift b/BaoAnGongFisher/StampAlbum/AddStampAlert.swift new file mode 100644 index 0000000..4351741 --- /dev/null +++ b/BaoAnGongFisher/StampAlbum/AddStampAlert.swift @@ -0,0 +1,39 @@ +// +// AddStampAlert.swift +// BaoAnGongFisher +// +// Created by nipapa on 2022/10/18. +// + +import SwiftUI + +struct AddStampAlert: View { + + let screenSize = UIScreen.main.bounds + @Binding var alertIsPresented: Bool + @Binding var newStampName: String + var boxTitle: String = "開郵票" + + var body: some View { + VStack { + Text(boxTitle) + TextField("魚名", text: $newStampName) + .textFieldStyle(RoundedBorderTextFieldStyle()) + } + .padding() + .frame(width: screenSize.width * 0.6, height: screenSize.height * 0.2) + .background(Color.cyan) + .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous)) + .shadow(color: Color.gray, radius: 15, x: -1, y: -1) + .offset(y: alertIsPresented ? screenSize.height * 0.2 : screenSize.height) + } +} + +struct AddStampAlert_Previews: PreviewProvider { + static var previews: some View { + AddStampAlert( + alertIsPresented: .constant(false), + newStampName: .constant("xx魚") + ) + } +} diff --git a/BaoAnGongFisher/StampAlbum/StampAlbumView.swift b/BaoAnGongFisher/StampAlbum/StampAlbumView.swift index 9e2d417..8e6eb2c 100644 --- a/BaoAnGongFisher/StampAlbum/StampAlbumView.swift +++ b/BaoAnGongFisher/StampAlbum/StampAlbumView.swift @@ -12,7 +12,7 @@ struct StampAlbumView: View { private let colors: [Color] = [ .red, .blue, .green, .yellow, .pink, .cyan, .indigo] // The photo and event state - // @State private var newStampPhoto = UIImage(systemName: "camera")! + @State private var addStampAlertIsPresented: Bool = false @State private var newStampPhoto = UIImage() @State private var showPhotoOptions = false @State private var photoSource: PhotoSource?