Integrate flashcard list into deck view

This commit is contained in:
2024-05-02 19:00:39 +02:00
parent 78818db778
commit c9e78a6c5f
6 changed files with 61 additions and 22 deletions

View File

@@ -23,16 +23,19 @@ class DataController: ObservableObject {
var deck = Deck(context: viewContext) var deck = Deck(context: viewContext)
deck.id = UUID() deck.id = UUID()
deck.name = "This is a deck name" deck.name = "This is a deck name"
deck.dateAdded = Date()
decks.append(deck) decks.append(deck)
deck = Deck(context: viewContext) deck = Deck(context: viewContext)
deck.id = UUID() deck.id = UUID()
deck.name = "Another Deck" deck.name = "Another Deck"
deck.dateAdded = Date().addingTimeInterval(-86400)
decks.append(deck) decks.append(deck)
deck = Deck(context: viewContext) deck = Deck(context: viewContext)
deck.id = UUID() deck.id = UUID()
deck.name = "Deck" deck.name = "Deck"
deck.dateAdded = Date().addingTimeInterval(-86400 * 2)
decks.append(deck) decks.append(deck)
for _ in 0..<10 { for _ in 0..<10 {
@@ -49,7 +52,7 @@ class DataController: ObservableObject {
flashcard.shownCount = [0, 1, 2, 3, 4, 5].randomElement()! flashcard.shownCount = [0, 1, 2, 3, 4, 5].randomElement()!
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()
} }
do { do {
try viewContext.save() try viewContext.save()

View File

@@ -18,6 +18,7 @@ extension Deck {
@NSManaged public var id: UUID? @NSManaged public var id: UUID?
@NSManaged public var name: String? @NSManaged public var name: String?
@NSManaged public var dateAdded: Date?
@NSManaged public var flashcards: NSSet? @NSManaged public var flashcards: NSSet?
} }

View File

@@ -1,17 +1,18 @@
<?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="23D60" 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="id" attributeType="UUID" usesScalarValueType="NO"/> <attribute name="id" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String"/> <attribute name="name" attributeType="String" spotlightIndexingEnabled="YES"/>
<relationship name="flashcards" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Flashcard" inverseName="deck" inverseEntity="Flashcard"/> <relationship name="flashcards" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Flashcard" inverseName="deck" inverseEntity="Flashcard"/>
</entity> </entity>
<entity name="Flashcard" representedClassName="Flashcard" syncable="YES" coreSpotlightDisplayNameExpression="Card"> <entity name="Flashcard" representedClassName="Flashcard" syncable="YES" coreSpotlightDisplayNameExpression="Card">
<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"/> <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="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"/> <attribute name="name" optional="YES" attributeType="String" spotlightIndexingEnabled="YES"/>
<attribute name="nextSpacedRepetitionMilestone" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="nextSpacedRepetitionMilestone" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="shown" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> <attribute name="shown" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="shownCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="shownCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>

View File

@@ -30,6 +30,7 @@ struct AddDeckView: View {
let deck = Deck(context: moc) let deck = Deck(context: moc)
deck.id = UUID() deck.id = UUID()
deck.name = name deck.name = name
deck.dateAdded = Date()
do { do {
try moc.save() try moc.save()
self.isShowing = false self.isShowing = false

View File

@@ -8,15 +8,20 @@
import SwiftUI import SwiftUI
struct DeckListView: View { struct DeckListView: View {
@FetchRequest(sortDescriptors: []) 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
var body: some View { var body: some View {
NavigationSplitView { NavigationStack {
List { List {
ForEach(decks) { deck in ForEach(decks) { deck in
NavigationLink {
FlashCardListView(deck: deck)
} label: {
Text(deck.name ?? "Unknown deck name") Text(deck.name ?? "Unknown deck name")
} }
}
.onDelete(perform: { offsets in .onDelete(perform: { offsets in
for index in offsets { for index in offsets {
let deck = decks[index] let deck = decks[index]
@@ -43,8 +48,6 @@ struct DeckListView: View {
} }
} }
.navigationTitle("All decks") .navigationTitle("All decks")
} detail: {
Text("Select deck to get details about")
} }
.sheet(isPresented: $addDeck, content: { .sheet(isPresented: $addDeck, content: {
AddDeckView(isShowing: $addDeck) AddDeckView(isShowing: $addDeck)

View File

@@ -6,15 +6,18 @@
// //
import SwiftUI import SwiftUI
import CoreData
struct FlashCardListView: View { struct FlashCardListView: View {
@State var showDescription = true @State var showDescription = true
@State var addFlashcard = false @State var addFlashcard: Bool = false
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "favorite", ascending: false), NSSortDescriptor(key: "dateAdded", ascending: false)]) var flashcards: FetchedResults<Flashcard> @State var flashcards: [Flashcard] = []
var deck: Deck?
@Environment(\.managedObjectContext) var moc @Environment(\.managedObjectContext) var moc
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
NavigationSplitView { NavigationStack {
Group { Group {
if !flashcards.isEmpty { if !flashcards.isEmpty {
List { List {
@@ -29,6 +32,7 @@ struct FlashCardListView: View {
for index in offsets { for index in offsets {
let flashcard = flashcards[index] let flashcard = flashcards[index]
moc.delete(flashcard) moc.delete(flashcard)
flashcards.remove(at: index)
} }
do { do {
@@ -39,16 +43,27 @@ struct FlashCardListView: View {
}) })
} }
} else { } else {
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)") 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() .padding()
.background(.purple) .background(.purple)
.clipShape(.buttonBorder) .clipShape(.buttonBorder)
.frame(maxWidth: geometry.size.width - 30) }
.frame(maxHeight: .infinity)
.padding(.horizontal)
} }
} }
.navigationTitle("All Flashcards") .onAppear {
refreshFlashcards()
}
.onChange(of: addFlashcard, { oldValue, newValue in
if oldValue {
refreshFlashcards()
}
})
.navigationBarTitle(deck?.name ?? "All Flashcards", displayMode: deck != nil ? .inline : .automatic)
.toolbar { .toolbar {
ToolbarItemGroup(placement: .topBarLeading) { ToolbarItemGroup(placement: .topBarTrailing) {
EditButton() EditButton()
} }
ToolbarItemGroup(placement: .topBarTrailing) { ToolbarItemGroup(placement: .topBarTrailing) {
@@ -59,14 +74,29 @@ struct FlashCardListView: View {
} }
} }
} }
} detail: {
Text("Select flashcard to get details about")
} }
.sheet(isPresented: $addFlashcard, content: { .sheet(isPresented: $addFlashcard, content: {
AddFlashCardView(isShowing: $addFlashcard) AddFlashCardView(isShowing: $addFlashcard, selectedDeck: deck)
}) })
} }
} }
private func refreshFlashcards() {
let request = NSFetchRequest<Flashcard>(entityName: "Flashcard")
request.sortDescriptors = [NSSortDescriptor(key: "favorite", ascending: false), NSSortDescriptor(key: "dateAdded", ascending: false)]
if deck != nil {
request.predicate = NSPredicate(format: "deck == %@", deck!)
// flashcards = deck?.flashcards?.allObjects as? [Flashcard] ?? []
}
do {
flashcards = try moc.fetch(request)
print(flashcards)
} catch {
print("Something went wrong while fetching the flashcards")
flashcards = []
}
}
} }
#Preview { #Preview {