Compare commits
	
		
			10 Commits
		
	
	
		
			880315ee53
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 65d3974d6c | |||
| f6c4e68698 | |||
| e11d79acb9 | |||
| a136ee333a | |||
| 492518ccdb | |||
| e0b6365eeb | |||
| 8e0fca1c36 | |||
| df267ebc4e | |||
| 5a5646648f | |||
| ecdea1de2f | 
| @@ -61,7 +61,7 @@ Why settle for pricey apps when you can have WordAX? We're here to prove that ef | |||||||
| - [x] Create flashcards | - [x] Create flashcards | ||||||
| - [ ] Add tags to cards | - [ ] Add tags to cards | ||||||
| - [ ] Specify how often you want each card to be seen (per folder/tag?) | - [ ] Specify how often you want each card to be seen (per folder/tag?) | ||||||
| - [ ] Add tags/folders | - [x] Add tags/folders - added decks to group cards | ||||||
| - [x] Store cards persistently | - [x] Store cards persistently | ||||||
| 	- [x] For start store them on the phone - stored using Core Data | 	- [x] For start store them on the phone - stored using Core Data | ||||||
| 	- [ ] Maybe later add a storage in cloud, so that you can sync with other devices if the app is multi-platform? | 	- [ ] Maybe later add a storage in cloud, so that you can sync with other devices if the app is multi-platform? | ||||||
| @@ -70,6 +70,7 @@ Why settle for pricey apps when you can have WordAX? We're here to prove that ef | |||||||
| - [ ] Make an apple watch version of the app | - [ ] Make an apple watch version of the app | ||||||
| - [ ] Option to add a hint | - [ ] Option to add a hint | ||||||
| - [ ] Add haptic touch | - [ ] Add haptic touch | ||||||
|  | - [ ] Add emoji to decks? design:) | ||||||
|  |  | ||||||
| <p align="right">(<a href="#readme-top">back to top</a>)</p> | <p align="right">(<a href="#readme-top">back to top</a>)</p> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
| /* Begin PBXBuildFile section */ | /* Begin PBXBuildFile section */ | ||||||
| 		6C4A87D22BE25D260074E0A9 /* Deck+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A87D02BE25D260074E0A9 /* Deck+CoreDataClass.swift */; }; | 		6C4A87D22BE25D260074E0A9 /* Deck+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A87D02BE25D260074E0A9 /* Deck+CoreDataClass.swift */; }; | ||||||
| 		6C4A87D32BE25D260074E0A9 /* Deck+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A87D12BE25D260074E0A9 /* Deck+CoreDataProperties.swift */; }; | 		6C4A87D32BE25D260074E0A9 /* Deck+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4A87D12BE25D260074E0A9 /* Deck+CoreDataProperties.swift */; }; | ||||||
|  | 		6C7B6D5D2BE69FA900FB6ECC /* DeckSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7B6D5C2BE69FA900FB6ECC /* DeckSelectView.swift */; }; | ||||||
|  | 		6C7B6D5F2BE6A1C100FB6ECC /* DeckRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7B6D5E2BE6A1C100FB6ECC /* DeckRowView.swift */; }; | ||||||
| 		6C8184FE2B88C9580033CF46 /* WordAX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8184FD2B88C9580033CF46 /* WordAX.swift */; }; | 		6C8184FE2B88C9580033CF46 /* WordAX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8184FD2B88C9580033CF46 /* WordAX.swift */; }; | ||||||
| 		6C8185002B88C9660033CF46 /* Miscellaneous.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8184FF2B88C9660033CF46 /* Miscellaneous.swift */; }; | 		6C8185002B88C9660033CF46 /* Miscellaneous.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8184FF2B88C9660033CF46 /* Miscellaneous.swift */; }; | ||||||
| 		6C8185022B88C9FB0033CF46 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8185012B88C9FB0033CF46 /* SettingsView.swift */; }; | 		6C8185022B88C9FB0033CF46 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C8185012B88C9FB0033CF46 /* SettingsView.swift */; }; | ||||||
| @@ -34,6 +36,8 @@ | |||||||
| /* Begin PBXFileReference section */ | /* Begin PBXFileReference section */ | ||||||
| 		6C4A87D02BE25D260074E0A9 /* Deck+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Deck+CoreDataClass.swift"; sourceTree = "<group>"; }; | 		6C4A87D02BE25D260074E0A9 /* Deck+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Deck+CoreDataClass.swift"; sourceTree = "<group>"; }; | ||||||
| 		6C4A87D12BE25D260074E0A9 /* Deck+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Deck+CoreDataProperties.swift"; sourceTree = "<group>"; }; | 		6C4A87D12BE25D260074E0A9 /* Deck+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Deck+CoreDataProperties.swift"; sourceTree = "<group>"; }; | ||||||
|  | 		6C7B6D5C2BE69FA900FB6ECC /* DeckSelectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeckSelectView.swift; path = WordAX/Views/Deck/DeckSelectView.swift; sourceTree = SOURCE_ROOT; }; | ||||||
|  | 		6C7B6D5E2BE6A1C100FB6ECC /* DeckRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeckRowView.swift; sourceTree = "<group>"; }; | ||||||
| 		6C8184FD2B88C9580033CF46 /* WordAX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordAX.swift; sourceTree = "<group>"; }; | 		6C8184FD2B88C9580033CF46 /* WordAX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordAX.swift; sourceTree = "<group>"; }; | ||||||
| 		6C8184FF2B88C9660033CF46 /* Miscellaneous.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Miscellaneous.swift; sourceTree = "<group>"; }; | 		6C8184FF2B88C9660033CF46 /* Miscellaneous.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Miscellaneous.swift; sourceTree = "<group>"; }; | ||||||
| 		6C8185012B88C9FB0033CF46 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; | 		6C8185012B88C9FB0033CF46 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; | ||||||
| @@ -109,7 +113,9 @@ | |||||||
| 		6CD2D7C92BE26FFB0079C4FA /* Deck */ = { | 		6CD2D7C92BE26FFB0079C4FA /* Deck */ = { | ||||||
| 			isa = PBXGroup; | 			isa = PBXGroup; | ||||||
| 			children = ( | 			children = ( | ||||||
|  | 				6C7B6D5E2BE6A1C100FB6ECC /* DeckRowView.swift */, | ||||||
| 				6CB09C2C2BE28C3E0020FE0C /* AddDeckView.swift */, | 				6CB09C2C2BE28C3E0020FE0C /* AddDeckView.swift */, | ||||||
|  | 				6C7B6D5C2BE69FA900FB6ECC /* DeckSelectView.swift */, | ||||||
| 				6CD2D7CA2BE270240079C4FA /* DeckListView.swift */, | 				6CD2D7CA2BE270240079C4FA /* DeckListView.swift */, | ||||||
| 			); | 			); | ||||||
| 			path = Deck; | 			path = Deck; | ||||||
| @@ -257,6 +263,7 @@ | |||||||
| 				6CF439542B83541D004C3543 /* MainView.swift in Sources */, | 				6CF439542B83541D004C3543 /* MainView.swift in Sources */, | ||||||
| 				6C8185082B8B523E0033CF46 /* NextRepetitionButtonView.swift in Sources */, | 				6C8185082B8B523E0033CF46 /* NextRepetitionButtonView.swift in Sources */, | ||||||
| 				6C8185062B8A537F0033CF46 /* FlashCardView.swift in Sources */, | 				6C8185062B8A537F0033CF46 /* FlashCardView.swift in Sources */, | ||||||
|  | 				6C7B6D5F2BE6A1C100FB6ECC /* DeckRowView.swift in Sources */, | ||||||
| 				6CEF7FA32BC88F6000E205F6 /* Flashcard+CoreDataProperties.swift in Sources */, | 				6CEF7FA32BC88F6000E205F6 /* Flashcard+CoreDataProperties.swift in Sources */, | ||||||
| 				6C81850A2B8BA5740033CF46 /* FlashCardListView.swift in Sources */, | 				6C81850A2B8BA5740033CF46 /* FlashCardListView.swift in Sources */, | ||||||
| 				6CEF7FA62BC96F2B00E205F6 /* ButtonHStackView.swift in Sources */, | 				6CEF7FA62BC96F2B00E205F6 /* ButtonHStackView.swift in Sources */, | ||||||
| @@ -271,6 +278,7 @@ | |||||||
| 				6CB09C2D2BE28C3E0020FE0C /* AddDeckView.swift in Sources */, | 				6CB09C2D2BE28C3E0020FE0C /* AddDeckView.swift in Sources */, | ||||||
| 				6C4A87D32BE25D260074E0A9 /* Deck+CoreDataProperties.swift in Sources */, | 				6C4A87D32BE25D260074E0A9 /* Deck+CoreDataProperties.swift in Sources */, | ||||||
| 				6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */, | 				6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */, | ||||||
|  | 				6C7B6D5D2BE69FA900FB6ECC /* DeckSelectView.swift in Sources */, | ||||||
| 				6C81850C2B8BA6BC0033CF46 /* FlashCardListRowView.swift in Sources */, | 				6C81850C2B8BA6BC0033CF46 /* FlashCardListRowView.swift in Sources */, | ||||||
| 				6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */, | 				6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */, | ||||||
| 			); | 			); | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ class DataController: ObservableObject { | |||||||
|             flashcard.dateAdded = [Date(), Date().addingTimeInterval(-86400), Date().addingTimeInterval(-172800)].randomElement()! |             flashcard.dateAdded = [Date(), Date().addingTimeInterval(-86400), Date().addingTimeInterval(-172800)].randomElement()! | ||||||
|             flashcard.favorite = [true, false].randomElement()! |             flashcard.favorite = [true, false].randomElement()! | ||||||
|             flashcard.deck = decks.randomElement() |             flashcard.deck = decks.randomElement() | ||||||
|  |             flashcard.hint = ["This is a small hint", "Hint", "This is a very long hint that maybe should be even longer olorem ipsum to cover everything but I don't know what else to write Lorem Ipsum", "This is something in between hint that doesn'coveres the mid cases Lorem Ipsujm Lor"].randomElement() | ||||||
|         } |         } | ||||||
|         do { |         do { | ||||||
|             try viewContext.save() |             try viewContext.save() | ||||||
|   | |||||||
| @@ -48,6 +48,7 @@ public class Flashcard: NSManagedObject { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum { |     func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum { | ||||||
|         SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone) |         let milestone = SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone) | ||||||
|  |         return milestone == .Now || milestone == .OneMinute ? .TenMinutes : milestone | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ extension Flashcard { | |||||||
|     @NSManaged public var shown: Bool |     @NSManaged public var shown: Bool | ||||||
|     @NSManaged public var shownCount: Int64 |     @NSManaged public var shownCount: Int64 | ||||||
|     @NSManaged public var deck: Deck? |     @NSManaged public var deck: Deck? | ||||||
|  |     @NSManaged public var hint: String? | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
| <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23D60" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier=""> | <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23E224" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier=""> | ||||||
|     <entity name="Deck" representedClassName="Deck" syncable="YES" coreSpotlightDisplayNameExpression="Deck"> |     <entity name="Deck" representedClassName="Deck" syncable="YES" coreSpotlightDisplayNameExpression="Deck"> | ||||||
|         <attribute name="dateAdded" attributeType="Date" defaultDateTimeInterval="736207200" usesScalarValueType="NO"/> |         <attribute name="dateAdded" attributeType="Date" defaultDateTimeInterval="736207200" usesScalarValueType="NO"/> | ||||||
|         <attribute name="id" attributeType="UUID" usesScalarValueType="NO"/> |         <attribute name="id" attributeType="UUID" usesScalarValueType="NO"/> | ||||||
| @@ -10,6 +10,7 @@ | |||||||
|         <attribute name="dateAdded" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |         <attribute name="dateAdded" optional="YES" attributeType="Date" usesScalarValueType="NO"/> | ||||||
|         <attribute name="desc" optional="YES" attributeType="String" spotlightIndexingEnabled="YES"/> |         <attribute name="desc" optional="YES" attributeType="String" spotlightIndexingEnabled="YES"/> | ||||||
|         <attribute name="favorite" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> |         <attribute name="favorite" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> | ||||||
|  |         <attribute name="hint" optional="YES" attributeType="String"/> | ||||||
|         <attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/> |         <attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/> | ||||||
|         <attribute name="lastSeenOn" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |         <attribute name="lastSeenOn" optional="YES" attributeType="Date" usesScalarValueType="NO"/> | ||||||
|         <attribute name="name" optional="YES" attributeType="String" spotlightIndexingEnabled="YES"/> |         <attribute name="name" optional="YES" attributeType="String" spotlightIndexingEnabled="YES"/> | ||||||
|   | |||||||
| @@ -16,24 +16,32 @@ struct AnkiView: View { | |||||||
|     @State var flashcards: [Flashcard] = [] |     @State var flashcards: [Flashcard] = [] | ||||||
|     @State var soonestFlashcards: [Flashcard] = [] |     @State var soonestFlashcards: [Flashcard] = [] | ||||||
|     @State var showDescription = false |     @State var showDescription = false | ||||||
|  |     @State var decksToDisplay = Set<Deck>() | ||||||
|  |     @State var deckViewVisible: Bool = false | ||||||
|  |      | ||||||
|      |      | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         Group { |  | ||||||
|             if !flashcards.isEmpty && flashcards.first != nil { |  | ||||||
|         GeometryReader { geometry in |         GeometryReader { geometry in | ||||||
|  |             VStack { | ||||||
|  |                 HStack { | ||||||
|  |                     Button { | ||||||
|  |                         self.deckViewVisible = true | ||||||
|  |                     } label: { | ||||||
|  |                         Image(systemName: "rectangle.stack.fill") | ||||||
|  |                             .padding([.leading, .top]) | ||||||
|  |                     } | ||||||
|  |                     Spacer() | ||||||
|  |                 } | ||||||
|  |                 if !flashcards.isEmpty && flashcards.first != nil { | ||||||
|                     VStack { |                     VStack { | ||||||
|                         if flashcards.first != nil { |                         if flashcards.first != nil { | ||||||
|                             FlashCardView(flashcard: flashcards.first!, showDescription: $showDescription) |                             FlashCardView(flashcard: flashcards.first!, showDescription: $showDescription) | ||||||
|                         } |                         } | ||||||
|                         if showDescription && flashcards.first != nil { |                         if showDescription && flashcards.first != nil { | ||||||
|                             //                    Text("How did you do?") |  | ||||||
|                             //                        .font(.subheadline) |  | ||||||
|                             //                        .foregroundStyle(.gray) |  | ||||||
|                             ButtonHStackView(flashcard: flashcards.first!, geometry: geometry, reload: refreshFlashcards, showDescription: $showDescription) |                             ButtonHStackView(flashcard: flashcards.first!, geometry: geometry, reload: refreshFlashcards, showDescription: $showDescription) | ||||||
|                                 .padding([.bottom, .trailing, .leading]) |                                 .padding([.bottom, .trailing, .leading]) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |  | ||||||
|                 } else { |                 } else { | ||||||
|                     if !soonestFlashcards.isEmpty { |                     if !soonestFlashcards.isEmpty { | ||||||
|                         Group { |                         Group { | ||||||
| @@ -57,6 +65,7 @@ struct AnkiView: View { | |||||||
|                                 .clipShape(.buttonBorder) |                                 .clipShape(.buttonBorder) | ||||||
|                                 .padding(.horizontal) |                                 .padding(.horizontal) | ||||||
|                         } |                         } | ||||||
|  |                         .frame(maxHeight: .infinity) | ||||||
|                     } |                     } | ||||||
|                     else { |                     else { | ||||||
|                         Text("No flashcards available") |                         Text("No flashcards available") | ||||||
| @@ -70,20 +79,34 @@ struct AnkiView: View { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         .onAppear { |         .onAppear { | ||||||
|             refreshFlashcards() |             refreshFlashcards() | ||||||
|         } |         } | ||||||
|  |         .sheet(isPresented: self.$deckViewVisible) { | ||||||
|  |             DeckSelectView(selection: $decksToDisplay, active: $deckViewVisible) | ||||||
|  |         } | ||||||
|  |         .onChange(of: deckViewVisible) { | ||||||
|  |             refreshFlashcards() | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     func refreshFlashcards() { |     func refreshFlashcards() { | ||||||
|         let requestAllFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard") |         let requestAllFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard") | ||||||
|         requestAllFlashcards.predicate = NSCompoundPredicate(type: .or, subpredicates: [ |         var predicateAllFlashcards = NSCompoundPredicate(type: .or, subpredicates: [ | ||||||
|             NSCompoundPredicate(type: .and, subpredicates: [ |             NSCompoundPredicate(type: .and, subpredicates: [ | ||||||
|                 NSPredicate(format: "%K != nil", "lastSeenOn"), |                 NSPredicate(format: "%K != nil", "lastSeenOn"), | ||||||
|                 NSPredicate(format: "lastSeenOn + nextSpacedRepetitionMilestone < %@", Date() as CVarArg) |                 NSPredicate(format: "lastSeenOn + nextSpacedRepetitionMilestone < %@", Date() as CVarArg) | ||||||
|             ]), |             ]), | ||||||
|             NSPredicate(format: "lastSeenOn == nil") |             NSPredicate(format: "lastSeenOn == nil") | ||||||
|         ]) |         ]) | ||||||
|  |         if !self.decksToDisplay.isEmpty { | ||||||
|  |             predicateAllFlashcards = NSCompoundPredicate(type: .and, subpredicates: [ | ||||||
|  |                 predicateAllFlashcards, | ||||||
|  |                 NSPredicate(format: "deck IN %@", decksToDisplay) | ||||||
|  |             ]) | ||||||
|  |         } | ||||||
|  |         requestAllFlashcards.predicate = predicateAllFlashcards | ||||||
|         requestAllFlashcards.sortDescriptors = [ |         requestAllFlashcards.sortDescriptors = [ | ||||||
|             NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false), |             NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false), | ||||||
|             NSSortDescriptor(key: "lastSeenOn", ascending: true) |             NSSortDescriptor(key: "lastSeenOn", ascending: true) | ||||||
| @@ -97,13 +120,16 @@ struct AnkiView: View { | |||||||
|          |          | ||||||
|          |          | ||||||
|         let requestSoonestFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard") |         let requestSoonestFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard") | ||||||
|         requestSoonestFlashcards.predicate = NSPredicate(format: "%K != nil", "lastSeenOn") |         var predicateSoonestFlashcards  = NSPredicate(format: "%K != nil", "lastSeenOn") | ||||||
|  |         if !self.decksToDisplay.isEmpty { | ||||||
|  |             predicateSoonestFlashcards = NSCompoundPredicate(type: .and, subpredicates: [ | ||||||
|  |                 predicateSoonestFlashcards, | ||||||
|  |                 NSPredicate(format: "deck IN %@", decksToDisplay) | ||||||
|  |             ]) | ||||||
|  |         } | ||||||
|  |         requestSoonestFlashcards.predicate = predicateSoonestFlashcards | ||||||
|         do { |         do { | ||||||
|             soonestFlashcards = try moc.fetch(requestSoonestFlashcards) |             soonestFlashcards = try moc.fetch(requestSoonestFlashcards) | ||||||
| //            print("This is soonest flashcards") |  | ||||||
| //            for flashcard in soonestFlashcards { |  | ||||||
| //                print("\(flashcard.name ?? "") is \(Int(flashcard.lastSeenOn!.addSpacedRepetitionMilestone(milestone:flashcard.getSpacedRepetitionMilestone()).timeIntervalSinceNow.rounded()))") |  | ||||||
| //            } |  | ||||||
|         } catch { |         } catch { | ||||||
|             print("Something went wrong while fetching latest flashcard") |             print("Something went wrong while fetching latest flashcard") | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -11,6 +11,16 @@ struct AddDeckView: View { | |||||||
|     @Binding var isShowing: Bool |     @Binding var isShowing: Bool | ||||||
|     @Environment(\.managedObjectContext) var moc |     @Environment(\.managedObjectContext) var moc | ||||||
|     @State var name: String = "" |     @State var name: String = "" | ||||||
|  |     @State var deck: Deck? | ||||||
|  |     var edit: Bool | ||||||
|  |      | ||||||
|  |     init(isShowing: Binding<Bool>, deck: Deck? = nil) { | ||||||
|  |         self._isShowing = isShowing | ||||||
|  |         self._name = State(initialValue: deck?.name ?? "") | ||||||
|  |         self.deck = deck | ||||||
|  |         self.edit = deck != nil | ||||||
|  |     } | ||||||
|  |      | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         NavigationStack { |         NavigationStack { | ||||||
|             List { |             List { | ||||||
| @@ -27,10 +37,14 @@ struct AddDeckView: View { | |||||||
|                 } |                 } | ||||||
|                 ToolbarItemGroup(placement: .topBarTrailing) { |                 ToolbarItemGroup(placement: .topBarTrailing) { | ||||||
|                     Button(action: { |                     Button(action: { | ||||||
|                         let deck = Deck(context: moc) |                         if let existingDeck = deck { | ||||||
|                         deck.id = UUID() |                             existingDeck.name = name | ||||||
|                         deck.name = name |                         } else { | ||||||
|                         deck.dateAdded = Date() |                             let currentDeck = Deck(context: moc) | ||||||
|  |                             currentDeck.id = UUID() | ||||||
|  |                             currentDeck.dateAdded = Date() | ||||||
|  |                             currentDeck.name = name | ||||||
|  |                         } | ||||||
|                         do { |                         do { | ||||||
|                             try moc.save() |                             try moc.save() | ||||||
|                             self.isShowing = false |                             self.isShowing = false | ||||||
| @@ -38,19 +52,21 @@ struct AddDeckView: View { | |||||||
|                             print("Something went wrong while saving the deck") |                             print("Something went wrong while saving the deck") | ||||||
|                         } |                         } | ||||||
|                     }, label: { |                     }, label: { | ||||||
|                         Text("Create") |                         Text(edit ? "Edit": "Create") | ||||||
|                             .bold() |                             .bold() | ||||||
|                     }) |                     }) | ||||||
|                     .disabled(name.isEmpty) |                     .disabled(name.isEmpty) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             .navigationTitle("Add Deck") |             .navigationTitle(edit ? "Edit Deck" : "Add Deck") | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #Preview { | #Preview { | ||||||
|     @State var isShowing = true |     @State var isShowing = true | ||||||
|     return AddDeckView(isShowing: $isShowing) |     let deck = Deck(context: DataController.preview.container.viewContext) | ||||||
|  |     deck.id = UUID() | ||||||
|  |     return AddDeckView(isShowing: $isShowing, deck: deck) | ||||||
|         .environment(\.managedObjectContext, DataController.preview.container.viewContext) |         .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,16 +11,38 @@ struct DeckListView: View { | |||||||
|     @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "dateAdded", ascending: false)]) var decks: FetchedResults<Deck> |     @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "dateAdded", ascending: false)]) var decks: FetchedResults<Deck> | ||||||
|     @State var addDeck = false |     @State var addDeck = false | ||||||
|     @Environment(\.managedObjectContext) var moc |     @Environment(\.managedObjectContext) var moc | ||||||
|     @State var addFlashcard = false |     @State var editDeck: Bool = false | ||||||
|  |     @State var deckToEdit: Deck? | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         NavigationStack { |         NavigationStack { | ||||||
|             List { |             List { | ||||||
|  |                 Button(action: { | ||||||
|  |                     self.addDeck = true | ||||||
|  |                 }) { | ||||||
|  |                     HStack { | ||||||
|  |                         Image(systemName: "plus.circle.fill") | ||||||
|  |                         Text("Add new deck") | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 ForEach(decks) { deck in |                 ForEach(decks) { deck in | ||||||
|  |                     HStack { | ||||||
|  |                         Button { | ||||||
|  |                             deckToEdit = deck | ||||||
|  |                             editDeck = true | ||||||
|  |                         } label: { | ||||||
|  |                             Image(systemName: "pencil") | ||||||
|  |                                 .contentShape(Rectangle()) | ||||||
|  |                                 .foregroundStyle(.blue) | ||||||
|  |                         } | ||||||
|  |                         .buttonStyle(PlainButtonStyle()) | ||||||
|  |                          | ||||||
|                         NavigationLink { |                         NavigationLink { | ||||||
|                             FlashCardListView(deck: deck) |                             FlashCardListView(deck: deck) | ||||||
|                         } label: { |                         } label: { | ||||||
|                             Text(deck.name ?? "Unknown deck name") |                             Text(deck.name ?? "Unknown deck name") | ||||||
|                         } |                         } | ||||||
|  |                         .contentShape(Rectangle()) | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|                 .onDelete(perform: { offsets in |                 .onDelete(perform: { offsets in | ||||||
|                     for index in offsets { |                     for index in offsets { | ||||||
| @@ -37,19 +59,19 @@ struct DeckListView: View { | |||||||
|             } |             } | ||||||
|             .toolbar { |             .toolbar { | ||||||
|                 ToolbarItemGroup(placement: .topBarTrailing) { |                 ToolbarItemGroup(placement: .topBarTrailing) { | ||||||
|                     Button(action: { |                     EditButton() | ||||||
|                         self.addDeck = true |  | ||||||
|                     }) { |  | ||||||
|                         Image(systemName: "plus") |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             .navigationTitle("All decks") |             .navigationTitle("All decks") | ||||||
|         } |         } | ||||||
|  |         .sheet(isPresented: Binding(get: {editDeck}, set: {editDeck = $0})) { | ||||||
|  |             AddDeckView(isShowing: $editDeck, deck: deckToEdit) | ||||||
|  |         } | ||||||
|         .sheet(isPresented: $addDeck, content: { |         .sheet(isPresented: $addDeck, content: { | ||||||
|             AddDeckView(isShowing: $addDeck) |             AddDeckView(isShowing: $addDeck) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |      | ||||||
| } | } | ||||||
|  |  | ||||||
| #Preview { | #Preview { | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								WordAX/Views/Deck/DeckRowView.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								WordAX/Views/Deck/DeckRowView.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | // | ||||||
|  | //  DeckRowView.swift | ||||||
|  | //  WordAX | ||||||
|  | // | ||||||
|  | //  Created by Oliver Hnát on 04.05.2024. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | import SwiftUI | ||||||
|  |  | ||||||
|  | struct DeckRowView: View { | ||||||
|  |     var deck: Deck | ||||||
|  |     var selected: Bool = false | ||||||
|  |     var body: some View { | ||||||
|  |         HStack { | ||||||
|  |             Text(deck.name ?? "Unknown") | ||||||
|  |             Spacer() | ||||||
|  |             if selected { | ||||||
|  |                 Image(systemName: "checkmark") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #Preview { | ||||||
|  |     let deck = try? DataController.preview.viewContext.fetch(Deck.fetchRequest()).first | ||||||
|  |     return DeckRowView(deck: deck!) | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								WordAX/Views/Deck/DeckSelectView.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								WordAX/Views/Deck/DeckSelectView.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | // | ||||||
|  | //  DeckSelectView.swift | ||||||
|  | //  WordAX | ||||||
|  | // | ||||||
|  | //  Created by Oliver Hnát on 04.05.2024. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | import SwiftUI | ||||||
|  |  | ||||||
|  | struct DeckSelectView: View { | ||||||
|  |     @FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)]) var decks: FetchedResults<Deck> | ||||||
|  |     @Binding var selection: Set<Deck> | ||||||
|  |     @Binding var active: Bool | ||||||
|  |     var body: some View { | ||||||
|  |         NavigationStack { | ||||||
|  |             List(decks, id:\.self, selection: $selection) { deck in | ||||||
|  |                 DeckRowView(deck: deck) | ||||||
|  |             } | ||||||
|  |             .environment(\.editMode, .constant(EditMode.active)) | ||||||
|  |             .toolbar { | ||||||
|  |                 ToolbarItemGroup(placement: .topBarTrailing) { | ||||||
|  |                     Button(action: { | ||||||
|  |                         self.active = false | ||||||
|  |                     }, label: { | ||||||
|  |                         Text("Done") | ||||||
|  |                             .bold() | ||||||
|  |                     }) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             .navigationTitle("Select Decks to display") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #Preview { | ||||||
|  |     @State var active = true | ||||||
|  |     @State var decksToDisplay = Set<Deck>() | ||||||
|  |     return DeckSelectView(selection: $decksToDisplay, active: $active) | ||||||
|  |         .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
|  | } | ||||||
| @@ -16,6 +16,9 @@ struct AddFlashCardView: View { | |||||||
|     @FetchRequest(sortDescriptors: []) var decks: FetchedResults<Deck> |     @FetchRequest(sortDescriptors: []) var decks: FetchedResults<Deck> | ||||||
|     @State var selectedDeck: Deck? |     @State var selectedDeck: Deck? | ||||||
|     @State var createDisabled: Bool = true |     @State var createDisabled: Bool = true | ||||||
|  |     @State var flashcard: Flashcard | ||||||
|  |     @State var hint: String = "" | ||||||
|  |     var edit: Bool = false | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         NavigationStack { |         NavigationStack { | ||||||
|             List { |             List { | ||||||
| @@ -23,6 +26,10 @@ struct AddFlashCardView: View { | |||||||
|                     TextField("Name", text: $text) |                     TextField("Name", text: $text) | ||||||
|                         .focused($focus) |                         .focused($focus) | ||||||
|                     TextField("Description", text: $description, axis: .vertical) |                     TextField("Description", text: $description, axis: .vertical) | ||||||
|  |                     TextField("Hint", text: $hint, axis: .vertical) | ||||||
|  |                         .lineLimit(3, reservesSpace: true) | ||||||
|  |                 } | ||||||
|  |                 Section(header: Text("Deck details")) { | ||||||
|                     Picker("Deck", selection: $selectedDeck) { |                     Picker("Deck", selection: $selectedDeck) { | ||||||
|                         ForEach(decks) { deck in |                         ForEach(decks) { deck in | ||||||
|                             Text(deck.name ?? "Unknown deck name") |                             Text(deck.name ?? "Unknown deck name") | ||||||
| @@ -54,7 +61,7 @@ struct AddFlashCardView: View { | |||||||
|                         self.createFlashcard() |                         self.createFlashcard() | ||||||
|                         self.isShowing = false |                         self.isShowing = false | ||||||
|                     }, label: { |                     }, label: { | ||||||
|                         Text("Create") |                         Text(edit ? "Save" : "Create") | ||||||
|                             .bold() |                             .bold() | ||||||
|                     }) |                     }) | ||||||
|                     .disabled(text.count == 0 || description.count == 0 || selectedDeck == nil) |                     .disabled(text.count == 0 || description.count == 0 || selectedDeck == nil) | ||||||
| @@ -65,15 +72,16 @@ struct AddFlashCardView: View { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     private func createFlashcard() { |     private func createFlashcard() { | ||||||
|         let flashcard = Flashcard(context: moc) |  | ||||||
|         flashcard.id = UUID() |  | ||||||
|         flashcard.name = self.text |         flashcard.name = self.text | ||||||
|         flashcard.desc = self.description |         flashcard.desc = self.description | ||||||
|  |         flashcard.deck = selectedDeck | ||||||
|  |         flashcard.hint = self.hint | ||||||
|  |         if !edit { | ||||||
|             flashcard.nextSpacedRepetitionMilestone = 0 |             flashcard.nextSpacedRepetitionMilestone = 0 | ||||||
|             flashcard.lastSeenOn = nil |             flashcard.lastSeenOn = nil | ||||||
|             flashcard.shownCount = 0 |             flashcard.shownCount = 0 | ||||||
|             flashcard.dateAdded = Date() |             flashcard.dateAdded = Date() | ||||||
|         flashcard.deck = selectedDeck |         } | ||||||
|         try? moc.save() |         try? moc.save() | ||||||
|  |  | ||||||
|     } |     } | ||||||
| @@ -81,6 +89,8 @@ struct AddFlashCardView: View { | |||||||
|  |  | ||||||
| #Preview { | #Preview { | ||||||
|     @State var isShowing = true |     @State var isShowing = true | ||||||
|     return AddFlashCardView(isShowing: $isShowing) |     let flashcard = Flashcard(context: DataController.preview.container.viewContext) | ||||||
|  |     flashcard.id = UUID() | ||||||
|  |     return AddFlashCardView(isShowing: $isShowing, flashcard: flashcard) | ||||||
|         .environment(\.managedObjectContext, DataController.preview.container.viewContext) |         .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import SwiftUI | |||||||
|  |  | ||||||
| struct FlashCardListRowView: View { | struct FlashCardListRowView: View { | ||||||
|     @State var flashcard: Flashcard |     @State var flashcard: Flashcard | ||||||
|     @State private var refresh: UUID = UUID() |     var refresh: () -> () | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         HStack { |         HStack { | ||||||
|             Group { |             Group { | ||||||
| @@ -31,9 +31,8 @@ struct FlashCardListRowView: View { | |||||||
|                 } catch { |                 } catch { | ||||||
|                     print("Something went wrong while saving favorite cards, please try again") |                     print("Something went wrong while saving favorite cards, please try again") | ||||||
|                 } |                 } | ||||||
|                 refresh = UUID() |                 refresh() | ||||||
|             } |             } | ||||||
|             .id(refresh) |  | ||||||
|             .padding(.trailing) |             .padding(.trailing) | ||||||
|             VStack { |             VStack { | ||||||
|                 Text(flashcard.name ?? "Unknown") |                 Text(flashcard.name ?? "Unknown") | ||||||
| @@ -52,12 +51,14 @@ struct FlashCardListRowView: View { | |||||||
|  |  | ||||||
| #Preview { | #Preview { | ||||||
|     let flashcard = try? DataController.preview.viewContext.fetch(Flashcard.fetchRequest()).first |     let flashcard = try? DataController.preview.viewContext.fetch(Flashcard.fetchRequest()).first | ||||||
|  |     func reloadPage() { | ||||||
|  |     } | ||||||
|     return Group { |     return Group { | ||||||
|         FlashCardListRowView(flashcard: flashcard!) |         FlashCardListRowView(flashcard: flashcard!, refresh: reloadPage) | ||||||
|             .environment(\.managedObjectContext, DataController.preview.container.viewContext) |             .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
|         FlashCardListRowView(flashcard: flashcard!) |         FlashCardListRowView(flashcard: flashcard!, refresh: reloadPage) | ||||||
|             .environment(\.managedObjectContext, DataController.preview.container.viewContext) |             .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
|         FlashCardListRowView(flashcard: flashcard!) |         FlashCardListRowView(flashcard: flashcard!, refresh: reloadPage) | ||||||
|             .environment(\.managedObjectContext, DataController.preview.container.viewContext) |             .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,17 +15,33 @@ struct FlashCardListView: View { | |||||||
|     var deck: Deck? |     var deck: Deck? | ||||||
|     @Environment(\.managedObjectContext) var moc |     @Environment(\.managedObjectContext) var moc | ||||||
|      |      | ||||||
|  |     private struct AddButton: View { | ||||||
|  |         @Binding var addFlashcard: Bool | ||||||
|  |         var text: String | ||||||
|  |         var body: some View { | ||||||
|  |             Button(action: { | ||||||
|  |                 self.addFlashcard = true | ||||||
|  |             }) { | ||||||
|  |                 HStack { | ||||||
|  |                     Image(systemName: "plus.circle.fill") | ||||||
|  |                         .padding(.trailing) | ||||||
|  |                     Text(text) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         GeometryReader { geometry in |         GeometryReader { geometry in | ||||||
|             NavigationStack { |             NavigationStack { | ||||||
|                 Group { |  | ||||||
|                     if !flashcards.isEmpty { |  | ||||||
|                 List { |                 List { | ||||||
|  |                     AddButton(addFlashcard: $addFlashcard, text: "Add new Flashcard") | ||||||
|  |                         .frame(maxHeight: geometry.size.height / 10) | ||||||
|                     ForEach(flashcards) { flashcard in |                     ForEach(flashcards) { flashcard in | ||||||
|                         NavigationLink { |                         NavigationLink { | ||||||
|                             FlashCardView(flashcard: flashcard, showDescription: $showDescription) |                             FlashCardView(flashcard: flashcard, showDescription: $showDescription) | ||||||
|                         } label: { |                         } label: { | ||||||
|                                     FlashCardListRowView(flashcard: flashcard) |                             FlashCardListRowView(flashcard: flashcard, refresh: refreshFlashcards) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     .onDelete(perform: { offsets in |                     .onDelete(perform: { offsets in | ||||||
| @@ -42,17 +58,7 @@ struct FlashCardListView: View { | |||||||
|                         } |                         } | ||||||
|                     }) |                     }) | ||||||
|                 } |                 } | ||||||
|                     } else { |                 .environment(\.defaultMinListRowHeight, geometry.size.height / 12) | ||||||
|                         Group { |  | ||||||
|                             Text("You currently don't have any flashcards. To add flashcards, either click at the '+' button at the top or you can download them from the store (coming soon)") |  | ||||||
|                                 .padding() |  | ||||||
|                                 .background(.purple) |  | ||||||
|                                 .clipShape(.buttonBorder) |  | ||||||
|                         } |  | ||||||
|                         .frame(maxHeight: .infinity) |  | ||||||
|                         .padding(.horizontal) |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 .onAppear { |                 .onAppear { | ||||||
|                     refreshFlashcards() |                     refreshFlashcards() | ||||||
|                 } |                 } | ||||||
| @@ -64,20 +70,22 @@ struct FlashCardListView: View { | |||||||
|                 .navigationBarTitle(deck?.name ?? "All Flashcards", displayMode: deck != nil ? .inline : .automatic) |                 .navigationBarTitle(deck?.name ?? "All Flashcards", displayMode: deck != nil ? .inline : .automatic) | ||||||
|                 .toolbar { |                 .toolbar { | ||||||
|                     ToolbarItemGroup(placement: .topBarTrailing) { |                     ToolbarItemGroup(placement: .topBarTrailing) { | ||||||
|                         Button(action: { |                         EditButton() | ||||||
|                             self.addFlashcard = true |  | ||||||
|                         }) { |  | ||||||
|                             Image(systemName: "plus") |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             .sheet(isPresented: $addFlashcard, content: { |             .sheet(isPresented: $addFlashcard, content: { | ||||||
|                 AddFlashCardView(isShowing: $addFlashcard, selectedDeck: deck) |                 AddFlashCardView(isShowing: $addFlashcard, selectedDeck: deck, flashcard: createFlashcard()) | ||||||
|             }) |             }) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     private func createFlashcard() -> Flashcard { | ||||||
|  |         let flashcard = Flashcard(context:moc) | ||||||
|  |         flashcard.id = UUID() | ||||||
|  |         return flashcard | ||||||
|  |     } | ||||||
|  |      | ||||||
|     private func refreshFlashcards() { |     private func refreshFlashcards() { | ||||||
|         let request = NSFetchRequest<Flashcard>(entityName: "Flashcard") |         let request = NSFetchRequest<Flashcard>(entityName: "Flashcard") | ||||||
|         request.sortDescriptors = [NSSortDescriptor(key: "favorite", ascending: false), NSSortDescriptor(key: "dateAdded", ascending: false)] |         request.sortDescriptors = [NSSortDescriptor(key: "favorite", ascending: false), NSSortDescriptor(key: "dateAdded", ascending: false)] | ||||||
| @@ -87,7 +95,6 @@ struct FlashCardListView: View { | |||||||
|         } |         } | ||||||
|         do { |         do { | ||||||
|             flashcards = try moc.fetch(request) |             flashcards = try moc.fetch(request) | ||||||
|             print(flashcards) |  | ||||||
|         } catch { |         } catch { | ||||||
|             print("Something went wrong while fetching the flashcards") |             print("Something went wrong while fetching the flashcards") | ||||||
|             flashcards = [] |             flashcards = [] | ||||||
|   | |||||||
| @@ -13,11 +13,13 @@ struct FlashCardView: View { | |||||||
|     var flashcard: Flashcard |     var flashcard: Flashcard | ||||||
|     @Binding var showDescription: Bool |     @Binding var showDescription: Bool | ||||||
|     @Environment(\.colorScheme) var colorScheme |     @Environment(\.colorScheme) var colorScheme | ||||||
|      |     @State var editFlashcard: Bool = false | ||||||
|  |     @State var showHint: Bool = false | ||||||
|      |      | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         let flashcardText = Text(flashcard.name ?? "Unknown") |         let flashcardText = Text(flashcard.name ?? "Unknown") | ||||||
|             .font(.title) |             .font(.title) | ||||||
|  |             .textSelection(.enabled) | ||||||
|             .bold() |             .bold() | ||||||
|         VStack { |         VStack { | ||||||
|             // TODO: Figure out if this and create/edit menu could be more similar? |             // TODO: Figure out if this and create/edit menu could be more similar? | ||||||
| @@ -32,7 +34,6 @@ struct FlashCardView: View { | |||||||
|                         .padding(.bottom) |                         .padding(.bottom) | ||||||
|                 } |                 } | ||||||
|                 flashcardText |                 flashcardText | ||||||
|                     .textSelection(.enabled) |  | ||||||
|                 Divider() |                 Divider() | ||||||
|                     .background(colorScheme == .light ? Color.black : Color.white) |                     .background(colorScheme == .light ? Color.black : Color.white) | ||||||
|                     .padding(.horizontal) |                     .padding(.horizontal) | ||||||
| @@ -41,6 +42,21 @@ struct FlashCardView: View { | |||||||
|             } else { |             } else { | ||||||
|                 flashcardText |                 flashcardText | ||||||
|             } |             } | ||||||
|  |             if !showDescription && flashcard.hint != nil { | ||||||
|  |                 if showHint { | ||||||
|  |                     Text((flashcard.hint != nil) ? "Hint: \(flashcard.hint ?? "")" : "") | ||||||
|  |                         .padding() | ||||||
|  |                         .font(.footnote) | ||||||
|  |                 } else { | ||||||
|  |                 } | ||||||
|  |                 Button { | ||||||
|  |                     showHint.toggle() | ||||||
|  |                 } label: { | ||||||
|  |                     Text(showHint ? "Hide Hint" : "Show Hint") | ||||||
|  |                         .padding() | ||||||
|  |                 } | ||||||
|  | //                .disabled(flashcard.hint == nil) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         .padding([.horizontal, .top]) |         .padding([.horizontal, .top]) | ||||||
|         .frame(maxWidth: .infinity, maxHeight: .infinity) |         .frame(maxWidth: .infinity, maxHeight: .infinity) | ||||||
| @@ -48,11 +64,21 @@ struct FlashCardView: View { | |||||||
|         .onTapGesture { |         .onTapGesture { | ||||||
|             self.showDescription = true |             self.showDescription = true | ||||||
|         } |         } | ||||||
|  |         .sheet(isPresented: $editFlashcard) { | ||||||
|  |             AddFlashCardView(text: flashcard.name ?? "", description: flashcard.desc ?? "", isShowing: $editFlashcard, selectedDeck: flashcard.deck, flashcard: flashcard, edit: true) | ||||||
|  |         } | ||||||
|  |         .toolbar { | ||||||
|  |             Button { | ||||||
|  |                 self.editFlashcard = true | ||||||
|  |             } label: { | ||||||
|  |                 Text("Edit") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #Preview { | #Preview { | ||||||
|     @State var showDescription = true |     @State var showDescription = false | ||||||
|     let flashcard = try? DataController.preview.viewContext.fetch(Flashcard.fetchRequest()).first |     let flashcard = try? DataController.preview.viewContext.fetch(Flashcard.fetchRequest()).first | ||||||
|     return FlashCardView(flashcard: flashcard!, showDescription: $showDescription) |     return FlashCardView(flashcard: flashcard!, showDescription: $showDescription) | ||||||
|         .environment(\.managedObjectContext, DataController.preview.container.viewContext) |         .environment(\.managedObjectContext, DataController.preview.container.viewContext) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user