2021-11-05 22:20:48 +00:00
|
|
|
//
|
|
|
|
// FlashCardView.swift
|
|
|
|
// Toki Trainer
|
|
|
|
//
|
|
|
|
// Created by Avery Ada Pace on 11/5/21.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
2021-11-07 18:03:41 +00:00
|
|
|
import CoreData
|
2021-11-05 22:20:48 +00:00
|
|
|
|
2021-11-07 06:25:18 +00:00
|
|
|
enum FlashCardResult {
|
|
|
|
case Correct
|
|
|
|
case Incorrect
|
|
|
|
case Unanswered
|
|
|
|
}
|
|
|
|
|
2021-11-05 22:20:48 +00:00
|
|
|
struct FlashCardView: View {
|
2021-11-06 03:55:05 +00:00
|
|
|
|
2021-11-06 17:35:56 +00:00
|
|
|
@ObservedObject var flashCardsViewModel = FlashCardsViewModel()
|
|
|
|
|
2021-11-09 18:17:22 +00:00
|
|
|
@State var currentLesson: String
|
|
|
|
@State var dictionary: [TokiDictEntry]
|
2021-11-08 17:24:46 +00:00
|
|
|
|
2021-12-03 18:58:18 +00:00
|
|
|
@State private var resultsShown = false
|
|
|
|
@State private var results: [String: Bool] = [:]
|
|
|
|
|
2021-11-09 18:17:22 +00:00
|
|
|
init(lesson: String, passedDictionary: [TokiDictEntry]) {
|
|
|
|
self.dictionary = passedDictionary
|
|
|
|
currentLesson = lesson
|
2021-11-08 17:24:46 +00:00
|
|
|
}
|
|
|
|
|
2021-11-06 03:55:05 +00:00
|
|
|
var body: some View {
|
|
|
|
VStack {
|
2021-12-03 18:58:18 +00:00
|
|
|
if !resultsShown {
|
|
|
|
FlashCardStack(currentLesson: currentLesson, dictionary: dictionary, resultsShown: $resultsShown, results: $results)
|
|
|
|
} else {
|
|
|
|
ResultsView(results: $results)
|
|
|
|
}
|
2021-11-08 17:24:46 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-06 03:55:05 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 06:25:18 +00:00
|
|
|
extension Binding {
|
|
|
|
func onChange(_ handler: @escaping () -> ()) -> Binding<Value> {
|
|
|
|
Binding(
|
|
|
|
get: { self.wrappedValue },
|
|
|
|
set: { newValue in
|
|
|
|
self.wrappedValue = newValue
|
|
|
|
handler()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-03 18:58:18 +00:00
|
|
|
struct ResultsView: View {
|
|
|
|
|
|
|
|
@Binding var results: [String: Bool]
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
VStack {
|
|
|
|
Text("Results")
|
|
|
|
.font(.title)
|
|
|
|
//ForEach(results.sorted(by: >), id: \.key) { key, value in
|
|
|
|
//ForEach(results.keys, id: \.self) { word in
|
|
|
|
List(Array(results.keys).sorted(by: <), id: \.self) { result in
|
|
|
|
Text(result)
|
|
|
|
.listRowBackground(results[result]! ? Color.green : Color.red)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-06 03:55:05 +00:00
|
|
|
struct FlashCardStack: View {
|
2021-11-07 18:03:41 +00:00
|
|
|
@Environment(\.managedObjectContext) private var viewContext
|
2021-11-06 03:55:05 +00:00
|
|
|
|
2021-11-07 23:12:21 +00:00
|
|
|
@FetchRequest(fetchRequest: K.getFlashCardAnswersFetchRequest) var flashCardAnswers: FetchedResults<FlashCardAnswer>
|
2021-11-09 18:17:22 +00:00
|
|
|
@FetchRequest(fetchRequest: K.getLessonAnswersFetchRequest) var lessonAnswers: FetchedResults<LessonAnswer>
|
2021-11-07 22:15:11 +00:00
|
|
|
|
2021-11-09 18:17:22 +00:00
|
|
|
var currentLesson: String
|
2021-11-06 20:17:43 +00:00
|
|
|
var dictionary: [TokiDictEntry]
|
2021-11-11 15:04:48 +00:00
|
|
|
@State private var shuffledDictionary: [TokiDictEntry] = []
|
2021-11-06 17:35:56 +00:00
|
|
|
@State private var flashCards: [FlashCard] = []
|
2021-11-06 20:17:43 +00:00
|
|
|
@State private var topFlashCard: FlashCard? = nil
|
2021-11-07 06:25:18 +00:00
|
|
|
@State private var flashCardsAreInteractive: [Bool] = []
|
2021-11-06 20:17:43 +00:00
|
|
|
@State private var flashCardsVertOffset: [CGFloat] = []
|
2021-11-07 06:25:18 +00:00
|
|
|
@State private var flashCardsResults: [FlashCardResult] = []
|
2021-11-09 19:34:29 +00:00
|
|
|
@State private var helperFadeOutOverlay = false
|
2021-12-03 18:58:18 +00:00
|
|
|
@State private var deckComplete = false
|
2021-11-06 20:17:43 +00:00
|
|
|
|
2021-12-03 18:58:18 +00:00
|
|
|
@Binding var resultsShown: Bool
|
|
|
|
@Binding var results: [String: Bool]
|
2021-11-06 20:17:43 +00:00
|
|
|
|
2021-12-03 18:58:18 +00:00
|
|
|
@State private var currentFlashCard = 0
|
2021-11-11 15:04:48 +00:00
|
|
|
|
2021-11-06 03:55:05 +00:00
|
|
|
var body: some View {
|
2021-11-06 17:35:56 +00:00
|
|
|
VStack {
|
|
|
|
ZStack {
|
2021-11-06 20:17:43 +00:00
|
|
|
if(flashCards.count > 0) {
|
|
|
|
ForEach(flashCards.indices, id: \.self) { index in
|
|
|
|
flashCards[index]
|
|
|
|
.offset(x: 0, y: flashCardsVertOffset[index])
|
2021-11-08 17:33:39 +00:00
|
|
|
.animation(.default, value: flashCardsVertOffset[index])
|
2021-11-08 17:24:46 +00:00
|
|
|
.zIndex(-(CGFloat(index * 10)))
|
2021-11-06 17:35:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-06 03:55:05 +00:00
|
|
|
}
|
2021-11-09 19:34:29 +00:00
|
|
|
}
|
|
|
|
.overlay(HStack {
|
|
|
|
Image(systemName: "arrow.backward")
|
|
|
|
Text("Incorrect")
|
|
|
|
Spacer()
|
|
|
|
Text("Correct")
|
|
|
|
Image(systemName: "arrow.right")
|
|
|
|
}.opacity(helperFadeOutOverlay ? 0.0 : 1.0), alignment: .top)
|
|
|
|
.onAppear {
|
|
|
|
initFlashCards()
|
2021-11-06 20:17:43 +00:00
|
|
|
}
|
2021-11-07 06:25:18 +00:00
|
|
|
Spacer()
|
2021-11-06 17:35:56 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 06:25:18 +00:00
|
|
|
func initFlashCards() {
|
2021-11-06 17:35:56 +00:00
|
|
|
flashCards = []
|
2021-11-11 15:04:48 +00:00
|
|
|
shuffledDictionary = dictionary
|
|
|
|
shuffledDictionary.shuffle()
|
|
|
|
for index in shuffledDictionary.indices {
|
2021-11-07 06:25:18 +00:00
|
|
|
flashCardsAreInteractive.append(false)
|
|
|
|
flashCardsResults.append(FlashCardResult.Unanswered)
|
2021-11-11 15:04:48 +00:00
|
|
|
flashCards.append(FlashCard(isInteractive: $flashCardsAreInteractive[index], result: $flashCardsResults[index].onChange(cardAnswerReceived), dictionaryEntry: shuffledDictionary[index]))
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset.append(370)
|
2021-11-07 06:25:18 +00:00
|
|
|
}
|
|
|
|
if flashCards.count - currentFlashCard >= 3 {
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
|
|
|
flashCardsVertOffset[currentFlashCard + 2] = 340
|
|
|
|
flashCardsVertOffset[currentFlashCard + 3] = 370
|
2021-11-07 06:25:18 +00:00
|
|
|
} else if flashCards.count - currentFlashCard == 2 {
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
|
|
|
flashCardsVertOffset[currentFlashCard + 2] = 340
|
2021-11-07 06:25:18 +00:00
|
|
|
} else if flashCards.count - currentFlashCard == 1 {
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
2021-11-06 03:55:05 +00:00
|
|
|
}
|
2021-11-07 06:25:18 +00:00
|
|
|
|
2021-11-08 17:42:03 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard] = 50
|
2021-11-07 06:25:18 +00:00
|
|
|
flashCardsAreInteractive[currentFlashCard] = true
|
2021-11-09 19:34:29 +00:00
|
|
|
|
|
|
|
resetLessonAnswersCoreData()
|
|
|
|
}
|
|
|
|
|
|
|
|
func resetLessonAnswersCoreData() {
|
|
|
|
for lessonAnswer in lessonAnswers {
|
|
|
|
if lessonAnswer.lesson == currentLesson {
|
|
|
|
viewContext.delete(lessonAnswer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try? viewContext.save()
|
2021-11-06 03:55:05 +00:00
|
|
|
}
|
2021-11-06 17:35:56 +00:00
|
|
|
|
2021-11-07 22:15:11 +00:00
|
|
|
func setFlashCardAnswersCoreData(_ correct: Bool) {
|
|
|
|
var cardInDatabase = false
|
|
|
|
for answer in flashCardAnswers {
|
2021-11-11 15:04:48 +00:00
|
|
|
if answer.word == shuffledDictionary[currentFlashCard].word {
|
2022-10-08 12:35:14 +00:00
|
|
|
print("word in database: \(answer.word ?? "nil")")
|
2021-11-07 23:51:48 +00:00
|
|
|
print("tries: \(answer.triesCount)")
|
|
|
|
print("correct`: \(answer.correctCount)")
|
2021-11-07 22:15:11 +00:00
|
|
|
cardInDatabase = true
|
|
|
|
answer.setValue((answer.triesCount + 1), forKey: "triesCount")
|
|
|
|
if correct {
|
|
|
|
answer.setValue((answer.correctCount + 1), forKey: "correctCount")
|
|
|
|
}
|
|
|
|
print("answer found in database")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 18:17:22 +00:00
|
|
|
var lessonInDatabase = false
|
|
|
|
for lessonAnswer in lessonAnswers {
|
|
|
|
if lessonAnswer.lesson == currentLesson {
|
|
|
|
lessonInDatabase = true
|
|
|
|
lessonAnswer.setValue((lessonAnswer.triesCount + 1), forKey: "triesCount")
|
|
|
|
if correct {
|
|
|
|
lessonAnswer.setValue((lessonAnswer.correctCount + 1), forKey: "correctCount")
|
|
|
|
}
|
|
|
|
print("lesson found in database")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if lessonInDatabase == false {
|
|
|
|
let lessonAnswer = LessonAnswer(context: viewContext)
|
|
|
|
lessonAnswer.lesson = currentLesson
|
|
|
|
lessonAnswer.triesCount = 1
|
|
|
|
if correct {
|
|
|
|
lessonAnswer.correctCount = 1
|
|
|
|
}
|
|
|
|
print("lesson not found in database")
|
|
|
|
}
|
|
|
|
|
2021-11-07 22:15:11 +00:00
|
|
|
if cardInDatabase == false {
|
|
|
|
let answer = FlashCardAnswer(context: viewContext)
|
2021-11-11 15:04:48 +00:00
|
|
|
answer.word = shuffledDictionary[currentFlashCard].word
|
2021-11-07 22:15:11 +00:00
|
|
|
answer.triesCount = 1
|
|
|
|
if correct {
|
|
|
|
answer.correctCount = 1
|
|
|
|
}
|
|
|
|
print("answer not found in database")
|
|
|
|
}
|
|
|
|
|
|
|
|
try? viewContext.save()
|
|
|
|
}
|
|
|
|
|
2021-11-07 18:03:41 +00:00
|
|
|
func cardAnswerReceived() {
|
|
|
|
if flashCardsResults[currentFlashCard] == FlashCardResult.Correct {
|
2021-11-07 22:15:11 +00:00
|
|
|
setFlashCardAnswersCoreData(true)
|
2021-11-07 18:03:41 +00:00
|
|
|
} else if flashCardsResults[currentFlashCard] == FlashCardResult.Incorrect {
|
2021-11-07 22:15:11 +00:00
|
|
|
setFlashCardAnswersCoreData(false)
|
2021-11-07 18:03:41 +00:00
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
nextFlashCard()
|
|
|
|
}
|
|
|
|
|
2021-11-06 20:17:43 +00:00
|
|
|
func nextFlashCard() {
|
2021-11-09 18:17:22 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard] = -1000
|
|
|
|
if currentFlashCard == (flashCards.count - 1) {
|
2021-12-03 18:58:18 +00:00
|
|
|
for (index, card) in flashCards.enumerated() {
|
|
|
|
self.results[card.dictionaryEntry.word] = (flashCardsResults[index] == FlashCardResult.Correct) ? true : false
|
|
|
|
}
|
|
|
|
self.resultsShown = true
|
2021-11-09 18:17:22 +00:00
|
|
|
return
|
2021-11-06 20:17:43 +00:00
|
|
|
}
|
2021-11-09 18:17:22 +00:00
|
|
|
currentFlashCard += 1
|
2021-11-08 17:42:03 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard] = 50
|
2021-11-07 06:25:18 +00:00
|
|
|
flashCardsAreInteractive[currentFlashCard] = true
|
|
|
|
|
2021-11-09 19:34:29 +00:00
|
|
|
self.helperFadeOutOverlay = true
|
2021-11-07 18:03:41 +00:00
|
|
|
|
2021-11-09 18:17:22 +00:00
|
|
|
if ((flashCards.count - 1) - currentFlashCard) > 3 {
|
|
|
|
print("flashCards: \(flashCards.count)")
|
|
|
|
print("currentFlashCard: \(currentFlashCard)")
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
|
|
|
flashCardsVertOffset[currentFlashCard + 2] = 340
|
|
|
|
flashCardsVertOffset[currentFlashCard + 3] = 370
|
2021-11-09 18:17:22 +00:00
|
|
|
} else if (flashCards.count - 1) - currentFlashCard > 2 {
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
|
|
|
flashCardsVertOffset[currentFlashCard + 2] = 340
|
2021-11-09 18:17:22 +00:00
|
|
|
} else if (flashCards.count - 1) - currentFlashCard > 1 {
|
2021-11-08 17:24:46 +00:00
|
|
|
flashCardsVertOffset[currentFlashCard + 1] = 310
|
2021-11-07 06:25:18 +00:00
|
|
|
}
|
2021-11-06 20:17:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func setTopFlashCard(card: FlashCard?) {
|
|
|
|
if let safeCard = card {
|
2021-11-07 06:25:18 +00:00
|
|
|
self.topFlashCard?.isInteractive = false
|
2021-11-06 20:17:43 +00:00
|
|
|
self.topFlashCard = safeCard
|
2021-11-07 06:25:18 +00:00
|
|
|
self.topFlashCard?.isInteractive = true
|
2021-11-06 20:17:43 +00:00
|
|
|
}
|
2021-11-06 17:35:56 +00:00
|
|
|
}
|
2021-11-06 03:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct FlashCard: View {
|
2021-11-05 22:20:48 +00:00
|
|
|
let screen = UIScreen.main.bounds
|
|
|
|
|
2021-11-06 00:23:33 +00:00
|
|
|
@State var isFaceDown = false
|
|
|
|
@State var rotationAngle: Double = 0
|
2021-11-07 06:25:18 +00:00
|
|
|
@Binding var isInteractive: Bool
|
|
|
|
@Binding var result: FlashCardResult
|
2021-11-06 17:35:56 +00:00
|
|
|
|
|
|
|
var dictionaryEntry: TokiDictEntry
|
2021-11-05 22:20:48 +00:00
|
|
|
|
2021-11-07 06:25:18 +00:00
|
|
|
@State private var dragAmount = CGFloat(0)
|
|
|
|
|
|
|
|
var drag: some Gesture {
|
|
|
|
DragGesture()
|
|
|
|
.onChanged { gesture in
|
|
|
|
if isInteractive {
|
|
|
|
self.dragAmount = gesture.translation.width
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.onEnded { gesture in
|
|
|
|
withAnimation {
|
|
|
|
if isInteractive {
|
|
|
|
if self.dragAmount < -20 {
|
|
|
|
self.dragAmount = -500
|
|
|
|
self.result = FlashCardResult.Incorrect
|
|
|
|
} else if self.dragAmount > 20 {
|
|
|
|
self.dragAmount = 500
|
|
|
|
self.result = FlashCardResult.Correct
|
2021-11-07 18:03:41 +00:00
|
|
|
} else {
|
|
|
|
self.dragAmount = 0
|
2021-11-07 06:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 22:20:48 +00:00
|
|
|
var body: some View {
|
|
|
|
|
2021-11-06 03:55:05 +00:00
|
|
|
Text("")
|
2021-11-06 17:35:56 +00:00
|
|
|
.modifier(CardFlipModifier(isFaceDown: isFaceDown, frontText: dictionaryEntry.word, backText: concatenateDefinitions()))
|
2021-12-03 18:58:18 +00:00
|
|
|
.frame(width: 300, height: 200)
|
2021-11-07 06:25:18 +00:00
|
|
|
.offset(x: isFaceDown ? -dragAmount : dragAmount, y: abs(dragAmount) / 10)
|
|
|
|
.rotationEffect(.degrees(isFaceDown ? -(dragAmount / 50) : dragAmount / 50))
|
2021-11-06 00:23:33 +00:00
|
|
|
.font(.title)
|
|
|
|
.rotation3DEffect(self.isFaceDown ? Angle(degrees: 180) : Angle(degrees: 0), axis: (x: 0.0, y: 10.0, z: 0.0))
|
2021-11-08 17:33:39 +00:00
|
|
|
.animation(.default, value: isFaceDown)
|
2021-11-08 20:00:21 +00:00
|
|
|
.animation(.default, value: dragAmount)
|
2021-11-06 00:23:33 +00:00
|
|
|
.onTapGesture {
|
2021-11-07 06:25:18 +00:00
|
|
|
if self.isInteractive == true {
|
2021-11-06 03:55:05 +00:00
|
|
|
self.isFaceDown.toggle()
|
|
|
|
}
|
2021-11-06 00:23:33 +00:00
|
|
|
}
|
2021-11-07 06:25:18 +00:00
|
|
|
.gesture(drag)
|
2021-11-06 03:55:05 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-11-06 17:35:56 +00:00
|
|
|
func concatenateDefinitions() -> String {
|
|
|
|
var result = String()
|
|
|
|
for definition in dictionaryEntry.definitions {
|
2021-11-07 06:25:18 +00:00
|
|
|
result.append(contentsOf: "\(definition.definition)\n")
|
2021-11-06 17:35:56 +00:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-11-06 03:55:05 +00:00
|
|
|
func setCanBeFlipped(_ input: Bool) {
|
2021-11-07 06:25:18 +00:00
|
|
|
self.isInteractive.toggle()
|
2021-11-05 22:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CardFlipModifier: AnimatableModifier {
|
2021-11-06 00:23:33 +00:00
|
|
|
|
|
|
|
var frontText: String
|
|
|
|
var backText: String
|
|
|
|
var isFaceDown: Bool
|
2021-11-05 22:20:48 +00:00
|
|
|
var rotationAngle: Double
|
|
|
|
|
2021-11-06 00:23:33 +00:00
|
|
|
init(isFaceDown: Bool, frontText: String, backText: String) {
|
|
|
|
rotationAngle = isFaceDown ? 180 : 0
|
|
|
|
self.isFaceDown = isFaceDown
|
|
|
|
self.frontText = frontText
|
|
|
|
self.backText = backText
|
2021-11-05 22:20:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var animatableData: Double {
|
|
|
|
get { rotationAngle }
|
|
|
|
set { rotationAngle = newValue }
|
|
|
|
}
|
|
|
|
|
|
|
|
func body(content: Content) -> some View {
|
2021-11-06 00:23:33 +00:00
|
|
|
return ZStack {
|
2021-11-05 22:20:48 +00:00
|
|
|
RoundedRectangle(cornerRadius: 20.0)
|
2021-11-07 22:52:36 +00:00
|
|
|
.fill(rotationAngle < 90 ? Color("CardColor") : Color("CardColorBack"))
|
2021-11-07 06:25:18 +00:00
|
|
|
.animation(.none, value: rotationAngle)
|
2021-11-06 03:55:05 +00:00
|
|
|
.overlay(
|
|
|
|
RoundedRectangle(cornerRadius: 20)
|
2021-11-07 22:52:36 +00:00
|
|
|
.stroke(Color("CardColorBack"), lineWidth: 5))
|
2021-11-07 06:25:18 +00:00
|
|
|
.animation(.none, value: rotationAngle)
|
2021-11-07 22:52:36 +00:00
|
|
|
Image("CardLogoDark")
|
|
|
|
.resizable()
|
|
|
|
.frame(width: 180, height: 180, alignment: .center)
|
|
|
|
.opacity(0.5)
|
2021-11-06 00:23:33 +00:00
|
|
|
Text(frontText)
|
|
|
|
.font(.title)
|
2021-11-07 22:52:36 +00:00
|
|
|
.foregroundColor(.white)
|
2021-11-05 22:20:48 +00:00
|
|
|
.opacity(rotationAngle < 90 ? 1.0 : 0.0)
|
2021-11-07 06:25:18 +00:00
|
|
|
.animation(.none, value: rotationAngle)
|
2021-11-06 00:23:33 +00:00
|
|
|
Text(backText)
|
|
|
|
.font(.subheadline)
|
|
|
|
.padding()
|
2021-11-07 22:52:36 +00:00
|
|
|
.foregroundColor(.white)
|
2021-11-06 00:23:33 +00:00
|
|
|
.opacity(rotationAngle < 90 ? 0.0 : 1.0)
|
2021-11-07 06:25:18 +00:00
|
|
|
.animation(.none, value: rotationAngle)
|
2021-11-06 00:23:33 +00:00
|
|
|
.scaleEffect(CGSize(width: -1.0, height: 1.0))
|
2021-11-05 22:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct FlashCardView_Previews: PreviewProvider {
|
2021-11-09 19:34:29 +00:00
|
|
|
static var lessonVM = FlashCardLessonsViewModel()
|
2021-11-09 18:17:22 +00:00
|
|
|
|
2021-11-05 22:20:48 +00:00
|
|
|
static var previews: some View {
|
2021-11-09 19:34:29 +00:00
|
|
|
FlashCardView(lesson: lessonVM.lessons[0].lesson, passedDictionary: lessonVM.lessons[0].words).environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
|
2021-11-05 22:20:48 +00:00
|
|
|
}
|
|
|
|
}
|