From ee1cd583ea3ca548dce3ac80e3dd2d447ddf7c71 Mon Sep 17 00:00:00 2001 From: Snesnopic Date: Thu, 16 May 2024 16:29:08 +0200 Subject: [PATCH 1/5] Migration to CoreData --- Morser.xcodeproj/project.pbxproj | 32 ++- Morser/Extensions.swift | 14 ++ Morser/Localizable.xcstrings | 2 +- Morser/Model/BindingWrapper.swift | 16 ++ Morser/Model/Sentence.swift | 32 --- Morser/Model/VibrationEngine.swift | 8 + Morser/Views/DataController.swift | 21 ++ Morser/Views/MorserApp.swift | 4 +- Morser/Views/ParentView.swift | 52 +++-- Morser/Views/QuickTranslateView.swift | 205 ++++++++++-------- .../Sentence.xcdatamodel/contents | 8 + 11 files changed, 246 insertions(+), 148 deletions(-) create mode 100644 Morser/Model/BindingWrapper.swift delete mode 100644 Morser/Model/Sentence.swift create mode 100644 Morser/Views/DataController.swift create mode 100644 Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents diff --git a/Morser.xcodeproj/project.pbxproj b/Morser.xcodeproj/project.pbxproj index 21647d9..89700d2 100644 --- a/Morser.xcodeproj/project.pbxproj +++ b/Morser.xcodeproj/project.pbxproj @@ -7,8 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 9D0CB0572BF5E78500FD8E57 /* Sentence.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 9D0CB0552BF5E78500FD8E57 /* Sentence.xcdatamodeld */; }; + 9D0CB0592BF5E87F00FD8E57 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0CB0582BF5E87F00FD8E57 /* DataController.swift */; }; 9D1CB9B02BCEB5930088F90C /* SpeechRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */; }; - 9D2099812BCD37AA00229594 /* Sentence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2099802BCD37AA00229594 /* Sentence.swift */; }; + 9D2099812BCD37AA00229594 /* BindingWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2099802BCD37AA00229594 /* BindingWrapper.swift */; }; 9D39222F2BCFB86E00FA1D05 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9D39222E2BCFB86E00FA1D05 /* Localizable.xcstrings */; }; 9D3DED2B2BCD109400DAD675 /* MorserApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3DED2A2BCD109400DAD675 /* MorserApp.swift */; }; 9D3DED2D2BCD109400DAD675 /* ParentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3DED2C2BCD109400DAD675 /* ParentView.swift */; }; @@ -27,9 +29,11 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 9D0CB0562BF5E78500FD8E57 /* Sentence.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Sentence.xcdatamodel; sourceTree = ""; }; + 9D0CB0582BF5E87F00FD8E57 /* DataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataController.swift; sourceTree = ""; }; 9D1CB9AE2BCEB2810088F90C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeechRecognizer.swift; sourceTree = ""; }; - 9D2099802BCD37AA00229594 /* Sentence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sentence.swift; sourceTree = ""; }; + 9D2099802BCD37AA00229594 /* BindingWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindingWrapper.swift; sourceTree = ""; }; 9D39222E2BCFB86E00FA1D05 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; 9D3DED272BCD109400DAD675 /* Morser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Morser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9D3DED2A2BCD109400DAD675 /* MorserApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MorserApp.swift; sourceTree = ""; }; @@ -67,7 +71,7 @@ 9DD425092BE3C5BF009EE623 /* BeepPlayer.swift */, 9D3DED412BCD248100DAD675 /* MorseEncoder.swift */, 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */, - 9D2099802BCD37AA00229594 /* Sentence.swift */, + 9D2099802BCD37AA00229594 /* BindingWrapper.swift */, ); path = Model; sourceTree = ""; @@ -130,6 +134,8 @@ 9D3DED3B2BCD16DE00DAD675 /* QuickTranslateView.swift */, 9D3DED3D2BCD16EB00DAD675 /* ListenView.swift */, 9D9BC1572BECE24200CD2C5B /* SettingsView.swift */, + 9D0CB0552BF5E78500FD8E57 /* Sentence.xcdatamodeld */, + 9D0CB0582BF5E87F00FD8E57 /* DataController.swift */, ); path = Views; sourceTree = ""; @@ -215,11 +221,13 @@ 9DD4250A2BE3C5BF009EE623 /* BeepPlayer.swift in Sources */, 9D3DED2D2BCD109400DAD675 /* ParentView.swift in Sources */, 9D1CB9B02BCEB5930088F90C /* SpeechRecognizer.swift in Sources */, - 9D2099812BCD37AA00229594 /* Sentence.swift in Sources */, + 9D2099812BCD37AA00229594 /* BindingWrapper.swift in Sources */, 9D3DED3C2BCD16DE00DAD675 /* QuickTranslateView.swift in Sources */, 9D3DED402BCD23E700DAD675 /* VibrationEngine.swift in Sources */, 9DA696702BCD7154002B9CBB /* Extensions.swift in Sources */, + 9D0CB0592BF5E87F00FD8E57 /* DataController.swift in Sources */, 9D3DED3E2BCD16EB00DAD675 /* ListenView.swift in Sources */, + 9D0CB0572BF5E78500FD8E57 /* Sentence.xcdatamodeld in Sources */, 9D3DED2B2BCD109400DAD675 /* MorserApp.swift in Sources */, 9D3DED3A2BCD167600DAD675 /* EncodeView.swift in Sources */, 9D3DED422BCD248100DAD675 /* MorseEncoder.swift in Sources */, @@ -380,6 +388,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MARKETING_VERSION = 1.2; + OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.snesnopic.Morser; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -423,6 +432,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MARKETING_VERSION = 1.2; + OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.snesnopic.Morser; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -456,6 +466,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + 9D0CB0552BF5E78500FD8E57 /* Sentence.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 9D0CB0562BF5E78500FD8E57 /* Sentence.xcdatamodel */, + ); + currentVersion = 9D0CB0562BF5E78500FD8E57 /* Sentence.xcdatamodel */; + name = Sentence.xcdatamodeld; + path = /Users/giuseppefrancione/Documents/Morser/Morser/Views/Sentence.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = 9D3DED1F2BCD109400DAD675 /* Project object */; } diff --git a/Morser/Extensions.swift b/Morser/Extensions.swift index 96b9941..74cc24d 100644 --- a/Morser/Extensions.swift +++ b/Morser/Extensions.swift @@ -36,4 +36,18 @@ extension String { func charAt(_ i: Int) -> Character { return Array(self)[i] } + + func morseCode() -> String { + return MorseEncoder.encode(string: self) + } +} + +extension FetchedResults { + func toArray() -> [Sentence] { + var array:[Sentence] = [] + self.forEach { result in + array.append(result) + } + return array + } } diff --git a/Morser/Localizable.xcstrings b/Morser/Localizable.xcstrings index e4366e5..af5b7a8 100644 --- a/Morser/Localizable.xcstrings +++ b/Morser/Localizable.xcstrings @@ -1165,4 +1165,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Morser/Model/BindingWrapper.swift b/Morser/Model/BindingWrapper.swift new file mode 100644 index 0000000..cc5b5fc --- /dev/null +++ b/Morser/Model/BindingWrapper.swift @@ -0,0 +1,16 @@ +// +// BindingWrapper.swift +// Morser +// +// Created by Giuseppe Francione on 15/04/24. +// + +import CoreData +import SwiftUI + +public class BindingWrapper: NSObject { + var boundSentence: Binding = .constant("") + init(_ string: String = "") { + self.boundSentence = .constant(string) + } +} diff --git a/Morser/Model/Sentence.swift b/Morser/Model/Sentence.swift deleted file mode 100644 index 71f4260..0000000 --- a/Morser/Model/Sentence.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Sentence.swift -// Morser -// -// Created by Giuseppe Francione on 15/04/24. -// - -import Foundation -import SwiftData -import SwiftUI -@Model -class Sentence{ - init(sentence: String, order: Int) { - self.sentence = sentence - self.order = order - } - var sentence: String - var boundSentence: Binding { - .init( - get: { - self.sentence - }, - set: { newValue in - self.sentence = newValue - } - ) - } - var order:Int - var morseCode:String { - return MorseEncoder.encode(string: sentence) - } -} diff --git a/Morser/Model/VibrationEngine.swift b/Morser/Model/VibrationEngine.swift index c20f995..6c11752 100644 --- a/Morser/Model/VibrationEngine.swift +++ b/Morser/Model/VibrationEngine.swift @@ -53,6 +53,14 @@ class VibrationEngine: ObservableObject { triggerNextVibration() } + func readMorseCode(sentence: Sentence) { + morseCodeIndex = 0 + morseCodeString = MorseEncoder.encode(string: sentence.sentence!) + if VibrationEngine.soundEnabled && dotPlayer == nil && dashPlayer == nil { + dotPlayer = BeepPlayer(frequency: 600, duration: dotDuration) + dashPlayer = BeepPlayer(frequency: 600, duration: dashDuration) + } + triggerNextVibration() } // Function to trigger vibrations based on Morse code func triggerNextVibration() { guard morseCodeIndex < morseCodeString.count else { diff --git a/Morser/Views/DataController.swift b/Morser/Views/DataController.swift new file mode 100644 index 0000000..75aa872 --- /dev/null +++ b/Morser/Views/DataController.swift @@ -0,0 +1,21 @@ +// +// DataController.swift +// Morser +// +// Created by Giuseppe Francione on 16/05/24. +// + +import Foundation +import CoreData +import SwiftUI + +class DataController: ObservableObject { + let container = NSPersistentContainer(name: "Sentence") + init() { + container.loadPersistentStores { description, error in + if let error = error { + print("Core Data failed to load: \(error.localizedDescription)") + } + } + } +} diff --git a/Morser/Views/MorserApp.swift b/Morser/Views/MorserApp.swift index bb2ef8a..ae94404 100644 --- a/Morser/Views/MorserApp.swift +++ b/Morser/Views/MorserApp.swift @@ -6,14 +6,14 @@ // import SwiftUI -import SwiftData @main struct MorserApp: App { + @StateObject private var dataController = DataController() var body: some Scene { WindowGroup { ParentView() + .environment(\.managedObjectContext, dataController.container.viewContext) } - .modelContainer(for: Sentence.self) } } diff --git a/Morser/Views/ParentView.swift b/Morser/Views/ParentView.swift index 970057a..ae0d85f 100644 --- a/Morser/Views/ParentView.swift +++ b/Morser/Views/ParentView.swift @@ -6,11 +6,11 @@ // import SwiftUI -import SwiftData +import CoreData struct ParentView: View { - @Query private var sentences: [Sentence] - @Environment(\.modelContext) private var modelContext: ModelContext + @FetchRequest(sortDescriptors: [SortDescriptor(\.order, order: .forward)]) private var sentences: FetchedResults + @Environment(\.managedObjectContext) var mocModelContext var body: some View { TabView { EncodeView().tabItem{ @@ -37,20 +37,29 @@ struct ParentView: View { } } .onAppear { - if sentences.isEmpty { - [ - Sentence(sentence: String(localized: "Yes, I can guide you."), order: 0), - Sentence(sentence: String(localized: "I'm here to help."), order: 1), - Sentence(sentence: String(localized: "I understand, let me assist you."), order: 2), - Sentence(sentence: String(localized: "I'll write it down for you."), order: 3), - Sentence(sentence: String(localized: "I'll describe the menu options for you."), order: 4), - Sentence(sentence: String(localized: "I'll help you navigate through touch."), order: 5), - Sentence(sentence: String(localized: "I'm communicating with you through touch."), order: 6), - Sentence(sentence: String(localized: "I'll lead you to the bus stop."), order: 7), - Sentence(sentence: String(localized: "Let me describe the location to you."), order: 8), - Sentence(sentence: String(localized: "I'll tap your hand to get your attention."), order: 9) - ].forEach { sentence in - modelContext.insert(sentence) + if sentences.toArray().isEmpty { + let strings = [ + String(localized: "I'm here to help."), + String(localized: "Yes, I can guide you."), + String(localized: "I understand, let me assist you."), + String(localized: "I'll write it down for you."), + String(localized: "I'll describe the menu options for you."), + String(localized: "I'll help you navigate through touch."), + String(localized: "I'm communicating with you through touch."), + String(localized: "I'll lead you to the bus stop."), + String(localized: "Let me describe the location to you."), + String(localized: "I'll tap your hand to get your attention.") + ] + var array:[Sentence] = [] + var index:Int32 = 0 + strings.forEach { string in + let sentence = Sentence(entity: Sentence.entity(), insertInto: mocModelContext) + sentence.sentence = string + sentence.order = index + index += 1 + sentence.bindingWrapper = BindingWrapper() + sentence.bindingWrapper?.boundSentence = .constant(string) + array.append(sentence) } } } @@ -58,8 +67,9 @@ struct ParentView: View { } #Preview { - let config = ModelConfiguration(isStoredInMemoryOnly: true) - let container = try! ModelContainer(for: Sentence.self, configurations: config) - - return ParentView().modelContainer(container) + // let config = ModelConfiguration(isStoredInMemoryOnly: true) + // let container = try! ModelContainer(for: Sentence.self, configurations: config) + // + return ParentView() + // .modelContainer(container) } diff --git a/Morser/Views/QuickTranslateView.swift b/Morser/Views/QuickTranslateView.swift index 378a258..a441641 100644 --- a/Morser/Views/QuickTranslateView.swift +++ b/Morser/Views/QuickTranslateView.swift @@ -9,72 +9,98 @@ import SwiftUI import SwiftData struct QuickTranslateView: View { - @Query(sort: \Sentence.order) private var sentences: [Sentence] - @Environment(\.modelContext) private var modelContext: ModelContext + @State var temporaryString: String = "" + @State var orderBeingChanged: Int32 = -2 + @FetchRequest(sortDescriptors: [SortDescriptor(\.order, order: .forward)]) private var sentences: FetchedResults + @Environment(\.managedObjectContext) var moc @State private var mode:EditMode = .inactive @FocusState private var textFieldIsFocused:Bool @ObservedObject private var vibrationEngine = VibrationEngine.shared + + private func vibrate(_ sentence:Sentence) { + if !vibrationEngine.isVibrating() { + vibrationEngine.createEngine() + vibrationEngine.readMorseCode(sentence: sentence) + } + } + var body: some View { NavigationStack { List { - ForEach(sentences) { sentence in - TextField("Insert a frequently used sentence",text: sentence.boundSentence) - .if(!mode.isEditing && sentence.order != -1, transform: { view in - view - .disabled(true) - .overlay { - Color.white.opacity(0.0001) - .onTapGesture { - if !vibrationEngine.isVibrating() { - vibrationEngine.createEngine() - vibrationEngine.readMorseCode(morseCode: sentence.morseCode) - } - } - } - - }) - .focused($textFieldIsFocused) - .onSubmit { - textFieldIsFocused = false - let tempItems = sentences - tempItems.indices.forEach({ index in - sentences.filter({ $0.sentence == tempItems[index].sentence}).first!.order = index - }) - do { - try modelContext.save() - } catch { - print(error) - } - } - .if(vibrationEngine.isVibrating() && vibrationEngine.morseCodeString == sentence.morseCode) { view in - view.listRowBackground(Color.accentColor) + ForEach(sentences.toArray().sorted(by: { sent1, sent2 in + return sent1.order < sent2.order + })) { sentence in + TextField("Insert a frequently used sentence",text: + orderBeingChanged != sentence.order ? sentence.bindingWrapper!.boundSentence : $temporaryString, onEditingChanged: { (changed) in + if changed { + temporaryString = sentence.bindingWrapper!.boundSentence.wrappedValue + orderBeingChanged = sentence.order + } else { + sentence.bindingWrapper = BindingWrapper(temporaryString) + temporaryString = "" + orderBeingChanged = -2 } - .if(vibrationEngine.isVibrating() && vibrationEngine.morseCodeString != sentence.morseCode) { view in - view - .disabled(true) - .foregroundStyle(Color.gray) + }) + .if(!mode.isEditing && sentence.order != -1, transform: { view in + view + .disabled(true) + .overlay { + Color.white.opacity(0.0001) + .onTapGesture { + vibrate(sentence) + } + } + }) + .focused($textFieldIsFocused) + .onSubmit { + sentence.sentence = sentence.bindingWrapper!.boundSentence.wrappedValue + textFieldIsFocused = false + let tempItems = sentences.toArray() + tempItems.indices.forEach({ index in + sentences.filter({ + $0.sentence! == tempItems[index].sentence! + }).first!.order = Int32(index) + sentences.filter({ $0.sentence == tempItems[index].sentence}).first!.order = Int32(index) + }) + do { + try moc.save() } - + catch { + print("Error: \(error)") + } } + .if(vibrationEngine.isVibrating() && vibrationEngine.morseCodeString == MorseEncoder.encode(string: sentence.sentence!)) { view in + view.listRowBackground(Color.accentColor) + } + .if(vibrationEngine.isVibrating() && vibrationEngine.morseCodeString != MorseEncoder.encode(string: sentence.sentence!)) { view in + view + .disabled(true) + .foregroundStyle(Color.gray) + } } .if(!vibrationEngine.isVibrating(), transform: { view in view .onDelete { indexSet in indexSet.forEach { index in - modelContext.delete(sentences[index]) + moc.delete(sentences[index]) + } + do { + try moc.save() + } + catch { + print("Error: \(error)") } } .onMove(perform: { source, destination in - var tempItems = sentences + var tempItems = sentences.toArray() tempItems.move(fromOffsets: source, toOffset: destination) - tempItems.indices.forEach({ index in - sentences.filter({ $0.sentence == tempItems[index].sentence}).first!.order = index + sentences.filter({ $0.sentence! == tempItems[index].sentence!}).first!.order = Int32(index) }) do { - try modelContext.save() + try moc.save() } catch { - print(error) + print("Error: \(error)") } }) }) @@ -90,7 +116,10 @@ struct QuickTranslateView: View { } ToolbarItem(placement: .topBarTrailing) { Button { - modelContext.insert(Sentence(sentence: "", order: -1)) + let newSentence = Sentence(entity: Sentence.entity(), insertInto: moc) + newSentence.order = -1 + newSentence.sentence = "" + newSentence.bindingWrapper = BindingWrapper() textFieldIsFocused = true } label: { @@ -105,46 +134,46 @@ struct QuickTranslateView: View { } } } -#Preview { - let config = ModelConfiguration(isStoredInMemoryOnly: true) - let container = try! ModelContainer(for: Sentence.self, configurations: config) - [ - Sentence(sentence: "Yes, I can guide you.", order: 0), - Sentence(sentence: "I'm here to help.", order: 1), - Sentence(sentence: "I understand, let me assist you.", order: 2), - Sentence(sentence: "I'll write it down for you.", order: 3), - Sentence(sentence: "I'll describe the menu options for you.", order: 4), - Sentence(sentence: "I'll help you navigate through touch.", order: 5), - Sentence(sentence: "I'm communicating with you through touch.", order: 6), - Sentence(sentence: "I'll lead you to the bus stop.", order: 7), - Sentence(sentence: "Let me describe the location to you.", order: 8), - Sentence(sentence: "I'll tap your hand to get your attention.", order: 9) - ].forEach { sentence in - container.mainContext.insert(sentence) - } - - return QuickTranslateView().modelContainer(container) -} - -#Preview ("Dark mode") { - let config = ModelConfiguration(isStoredInMemoryOnly: true) - let container = try! ModelContainer(for: Sentence.self, configurations: config) - [ - Sentence(sentence: "Yes, I can guide you.", order: 0), - Sentence(sentence: "I'm here to help.", order: 1), - Sentence(sentence: "I understand, let me assist you.", order: 2), - Sentence(sentence: "I'll write it down for you.", order: 3), - Sentence(sentence: "I'll describe the menu options for you.", order: 4), - Sentence(sentence: "I'll help you navigate through touch.", order: 5), - Sentence(sentence: "I'm communicating with you through touch.", order: 6), - Sentence(sentence: "I'll lead you to the bus stop.", order: 7), - Sentence(sentence: "Let me describe the location to you.", order: 8), - Sentence(sentence: "I'll tap your hand to get your attention.", order: 9) - ].forEach { sentence in - container.mainContext.insert(sentence) - } - - return QuickTranslateView() - .modelContainer(container) - .preferredColorScheme(.dark) -} +//#Preview { +// let config = ModelConfiguration(isStoredInMemoryOnly: true) +// let container = try! ModelContainer(for: Sentence.self, configurations: config) +// [ +// Sentence(sentence: "Yes, I can guide you.", order: 0), +// Sentence(sentence: "I'm here to help.", order: 1), +// Sentence(sentence: "I understand, let me assist you.", order: 2), +// Sentence(sentence: "I'll write it down for you.", order: 3), +// Sentence(sentence: "I'll describe the menu options for you.", order: 4), +// Sentence(sentence: "I'll help you navigate through touch.", order: 5), +// Sentence(sentence: "I'm communicating with you through touch.", order: 6), +// Sentence(sentence: "I'll lead you to the bus stop.", order: 7), +// Sentence(sentence: "Let me describe the location to you.", order: 8), +// Sentence(sentence: "I'll tap your hand to get your attention.", order: 9) +// ].forEach { sentence in +// container.mainContext.insert(sentence) +// } +// +// return QuickTranslateView().modelContainer(container) +//} +// +//#Preview ("Dark mode") { +// let config = ModelConfiguration(isStoredInMemoryOnly: true) +// let container = try! ModelContainer(for: Sentence.self, configurations: config) +// [ +// Sentence(sentence: "Yes, I can guide you.", order: 0), +// Sentence(sentence: "I'm here to help.", order: 1), +// Sentence(sentence: "I understand, let me assist you.", order: 2), +// Sentence(sentence: "I'll write it down for you.", order: 3), +// Sentence(sentence: "I'll describe the menu options for you.", order: 4), +// Sentence(sentence: "I'll help you navigate through touch.", order: 5), +// Sentence(sentence: "I'm communicating with you through touch.", order: 6), +// Sentence(sentence: "I'll lead you to the bus stop.", order: 7), +// Sentence(sentence: "Let me describe the location to you.", order: 8), +// Sentence(sentence: "I'll tap your hand to get your attention.", order: 9) +// ].forEach { sentence in +// container.mainContext.insert(sentence) +// } +// +// return QuickTranslateView() +// .modelContainer(container) +// .preferredColorScheme(.dark) +//} diff --git a/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents b/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents new file mode 100644 index 0000000..fc0f2c9 --- /dev/null +++ b/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents @@ -0,0 +1,8 @@ + + + + + + + + From ef8b2ca8adcd42ac80db53cde5f03af4978efae9 Mon Sep 17 00:00:00 2001 From: Snesnopic Date: Thu, 16 May 2024 17:05:51 +0200 Subject: [PATCH 2/5] Binding Wrapper not needed anymore --- Morser.xcodeproj/project.pbxproj | 4 ---- Morser/Model/BindingWrapper.swift | 16 ---------------- 2 files changed, 20 deletions(-) delete mode 100644 Morser/Model/BindingWrapper.swift diff --git a/Morser.xcodeproj/project.pbxproj b/Morser.xcodeproj/project.pbxproj index 89700d2..b9b5fad 100644 --- a/Morser.xcodeproj/project.pbxproj +++ b/Morser.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 9D0CB0572BF5E78500FD8E57 /* Sentence.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 9D0CB0552BF5E78500FD8E57 /* Sentence.xcdatamodeld */; }; 9D0CB0592BF5E87F00FD8E57 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0CB0582BF5E87F00FD8E57 /* DataController.swift */; }; 9D1CB9B02BCEB5930088F90C /* SpeechRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */; }; - 9D2099812BCD37AA00229594 /* BindingWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2099802BCD37AA00229594 /* BindingWrapper.swift */; }; 9D39222F2BCFB86E00FA1D05 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9D39222E2BCFB86E00FA1D05 /* Localizable.xcstrings */; }; 9D3DED2B2BCD109400DAD675 /* MorserApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3DED2A2BCD109400DAD675 /* MorserApp.swift */; }; 9D3DED2D2BCD109400DAD675 /* ParentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3DED2C2BCD109400DAD675 /* ParentView.swift */; }; @@ -33,7 +32,6 @@ 9D0CB0582BF5E87F00FD8E57 /* DataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataController.swift; sourceTree = ""; }; 9D1CB9AE2BCEB2810088F90C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeechRecognizer.swift; sourceTree = ""; }; - 9D2099802BCD37AA00229594 /* BindingWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindingWrapper.swift; sourceTree = ""; }; 9D39222E2BCFB86E00FA1D05 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; 9D3DED272BCD109400DAD675 /* Morser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Morser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9D3DED2A2BCD109400DAD675 /* MorserApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MorserApp.swift; sourceTree = ""; }; @@ -71,7 +69,6 @@ 9DD425092BE3C5BF009EE623 /* BeepPlayer.swift */, 9D3DED412BCD248100DAD675 /* MorseEncoder.swift */, 9D1CB9AF2BCEB5930088F90C /* SpeechRecognizer.swift */, - 9D2099802BCD37AA00229594 /* BindingWrapper.swift */, ); path = Model; sourceTree = ""; @@ -221,7 +218,6 @@ 9DD4250A2BE3C5BF009EE623 /* BeepPlayer.swift in Sources */, 9D3DED2D2BCD109400DAD675 /* ParentView.swift in Sources */, 9D1CB9B02BCEB5930088F90C /* SpeechRecognizer.swift in Sources */, - 9D2099812BCD37AA00229594 /* BindingWrapper.swift in Sources */, 9D3DED3C2BCD16DE00DAD675 /* QuickTranslateView.swift in Sources */, 9D3DED402BCD23E700DAD675 /* VibrationEngine.swift in Sources */, 9DA696702BCD7154002B9CBB /* Extensions.swift in Sources */, diff --git a/Morser/Model/BindingWrapper.swift b/Morser/Model/BindingWrapper.swift deleted file mode 100644 index cc5b5fc..0000000 --- a/Morser/Model/BindingWrapper.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// BindingWrapper.swift -// Morser -// -// Created by Giuseppe Francione on 15/04/24. -// - -import CoreData -import SwiftUI - -public class BindingWrapper: NSObject { - var boundSentence: Binding = .constant("") - init(_ string: String = "") { - self.boundSentence = .constant(string) - } -} From 45795e289ce718ab5af8f8342e42286bbf3b2316 Mon Sep 17 00:00:00 2001 From: Snesnopic Date: Thu, 16 May 2024 17:06:35 +0200 Subject: [PATCH 3/5] Now binding is manual binding of the variable --- Morser/Views/QuickTranslateView.swift | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/Morser/Views/QuickTranslateView.swift b/Morser/Views/QuickTranslateView.swift index a441641..c890605 100644 --- a/Morser/Views/QuickTranslateView.swift +++ b/Morser/Views/QuickTranslateView.swift @@ -9,8 +9,6 @@ import SwiftUI import SwiftData struct QuickTranslateView: View { - @State var temporaryString: String = "" - @State var orderBeingChanged: Int32 = -2 @FetchRequest(sortDescriptors: [SortDescriptor(\.order, order: .forward)]) private var sentences: FetchedResults @Environment(\.managedObjectContext) var moc @State private var mode:EditMode = .inactive @@ -30,17 +28,11 @@ struct QuickTranslateView: View { ForEach(sentences.toArray().sorted(by: { sent1, sent2 in return sent1.order < sent2.order })) { sentence in - TextField("Insert a frequently used sentence",text: - orderBeingChanged != sentence.order ? sentence.bindingWrapper!.boundSentence : $temporaryString, onEditingChanged: { (changed) in - if changed { - temporaryString = sentence.bindingWrapper!.boundSentence.wrappedValue - orderBeingChanged = sentence.order - } else { - sentence.bindingWrapper = BindingWrapper(temporaryString) - temporaryString = "" - orderBeingChanged = -2 - } - }) + TextField("Insert a frequently used sentence",text: Binding(get: { + sentence.sentence! + }, set: { newValue in + sentence.sentence! = newValue + })) .if(!mode.isEditing && sentence.order != -1, transform: { view in view .disabled(true) @@ -53,7 +45,6 @@ struct QuickTranslateView: View { }) .focused($textFieldIsFocused) .onSubmit { - sentence.sentence = sentence.bindingWrapper!.boundSentence.wrappedValue textFieldIsFocused = false let tempItems = sentences.toArray() tempItems.indices.forEach({ index in @@ -63,11 +54,12 @@ struct QuickTranslateView: View { sentences.filter({ $0.sentence == tempItems[index].sentence}).first!.order = Int32(index) }) do { - try moc.save() + try moc.save() } catch { print("Error: \(error)") - } } + } + } .if(vibrationEngine.isVibrating() && vibrationEngine.morseCodeString == MorseEncoder.encode(string: sentence.sentence!)) { view in view.listRowBackground(Color.accentColor) } @@ -116,10 +108,9 @@ struct QuickTranslateView: View { } ToolbarItem(placement: .topBarTrailing) { Button { - let newSentence = Sentence(entity: Sentence.entity(), insertInto: moc) + let newSentence = Sentence(context: moc) newSentence.order = -1 newSentence.sentence = "" - newSentence.bindingWrapper = BindingWrapper() textFieldIsFocused = true } label: { From 03ed8be6b96777c1f3e9dd84ae5e42852b9e4115 Mon Sep 17 00:00:00 2001 From: Snesnopic Date: Thu, 16 May 2024 17:06:55 +0200 Subject: [PATCH 4/5] Removed useless variable --- Morser/Views/ParentView.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Morser/Views/ParentView.swift b/Morser/Views/ParentView.swift index ae0d85f..e5bd886 100644 --- a/Morser/Views/ParentView.swift +++ b/Morser/Views/ParentView.swift @@ -57,8 +57,6 @@ struct ParentView: View { sentence.sentence = string sentence.order = index index += 1 - sentence.bindingWrapper = BindingWrapper() - sentence.bindingWrapper?.boundSentence = .constant(string) array.append(sentence) } } From 770c66a68210f5e5dac18d6e006eea7ea3343fe1 Mon Sep 17 00:00:00 2001 From: Snesnopic Date: Thu, 16 May 2024 17:07:07 +0200 Subject: [PATCH 5/5] Removed binding wrapper --- .../Sentence.xcdatamodeld/Sentence.xcdatamodel/contents | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents b/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents index fc0f2c9..c1e2348 100644 --- a/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents +++ b/Morser/Views/Sentence.xcdatamodeld/Sentence.xcdatamodel/contents @@ -1,8 +1,7 @@ - - - + +