Make the app more stable

This commit is contained in:
2024-02-25 17:34:12 +01:00
parent 69ffe49e8a
commit 0ffb96cf9c
5 changed files with 58 additions and 27 deletions

View File

@@ -9,7 +9,7 @@ import SwiftUI
struct AnkiView: View { struct AnkiView: View {
@EnvironmentObject var model: WordAXModelView @EnvironmentObject var model: WordAXModelView
@State var showDescription = true @State var showDescription = false
var word: WordAX.Word? { var word: WordAX.Word? {
model.getWordToDisplay() model.getWordToDisplay()
} }
@@ -18,13 +18,13 @@ struct AnkiView: View {
VStack { VStack {
WordView(word: word!, showDescription: $showDescription) WordView(word: word!, showDescription: $showDescription)
if showDescription { if showDescription {
Text("How did you do?") // Text("How did you do?")
.font(.subheadline) // .font(.subheadline)
.foregroundStyle(.gray) // .foregroundStyle(.gray)
HStack { HStack {
NextRepetitionButtonView(buttonText: "Poor", nextMilestone: word!.nextSpacedRepetitionMilestone, wordId: word!.id) NextRepetitionButtonView(buttonText: "Easy", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: word!.nextSpacedRepetitionMilestone)), wordId: word!.id, showDescription: $showDescription)
NextRepetitionButtonView(buttonText: "Good", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: word!.nextSpacedRepetitionMilestone), wordId: word!.id) NextRepetitionButtonView(buttonText: "Medium", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: word!.nextSpacedRepetitionMilestone), wordId: word!.id, showDescription: $showDescription)
NextRepetitionButtonView(buttonText: "Excellent", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: word!.nextSpacedRepetitionMilestone)), wordId: word!.id) NextRepetitionButtonView(buttonText: "Hard/Wrong", nextMilestone: word!.nextSpacedRepetitionMilestone, wordId: word!.id, showDescription: $showDescription)
} }
.padding(.bottom) .padding(.bottom)
} }

View File

@@ -11,11 +11,13 @@ struct NextRepetitionButtonView: View {
let buttonText: String let buttonText: String
let nextMilestone: WordAX.SpacedRepetitionMilestoneEnum? let nextMilestone: WordAX.SpacedRepetitionMilestoneEnum?
let wordId: Int let wordId: Int
@Binding var showDescription: Bool
@EnvironmentObject var model: WordAXModelView @EnvironmentObject var model: WordAXModelView
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
var body: some View { var body: some View {
Button(action: { Button(action: {
model.setSpacedRepetitionMilestone(wordId: wordId, milestone: nextMilestone) model.ankiButtonClicked(wordId: wordId, milestone: nextMilestone)
self.showDescription = false
}) { }) {
Text(buttonText) Text(buttonText)
.padding() .padding()
@@ -34,6 +36,7 @@ extension ShapeStyle where Self == Color {
} }
#Preview { #Preview {
NextRepetitionButtonView(buttonText: "Excellent", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.OneDay, wordId: 0) @State var showDescription = false
return NextRepetitionButtonView(buttonText: "Excellent", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.OneDay, wordId: 0, showDescription: $showDescription)
.environmentObject(WordAXModelView()) .environmentObject(WordAXModelView())
} }

View File

@@ -8,13 +8,14 @@
import Foundation import Foundation
struct WordAX { struct WordAX {
struct Word: Identifiable { struct Word: Identifiable, Hashable {
var id: Int var id: Int
var name: String var name: String
var description: String var description: String
var shown: Bool var shown: Bool
var nextSpacedRepetitionMilestone: SpacedRepetitionMilestoneEnum? var nextSpacedRepetitionMilestone: SpacedRepetitionMilestoneEnum?
var lastSeenOn: Date? var lastSeenOn: Date?
var shownCount: Int = 0
} }
enum FrequencyEnum: Int { enum FrequencyEnum: Int {
case Daily = 1 case Daily = 1
@@ -71,7 +72,19 @@ struct WordAX {
let index = words.firstIndex(where:{$0.id == wordId}) ?? nil let index = words.firstIndex(where:{$0.id == wordId}) ?? nil
if index != nil { if index != nil {
words[index!].nextSpacedRepetitionMilestone = milestone words[index!].nextSpacedRepetitionMilestone = milestone
if !words[index!].shown {
words[index!].shown = true
} }
words[index!].lastSeenOn = Date()
}
}
public mutating func wordShown(wordId: Int) {
let index = words.firstIndex(where:{$0.id == wordId}) ?? nil
if index != nil {
words[index!].shownCount += 1
}
} }
var words: [Word] = [] var words: [Word] = []
@@ -80,7 +93,7 @@ struct WordAX {
init() { init() {
self.words = [] self.words = []
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/mm/YYYY" dateFormatter.dateFormat = "dd/MM/YYYY"
self.settings = Settings(dateFormatter: dateFormatter) self.settings = Settings(dateFormatter: dateFormatter)
self.words.append(Word(id: 0, name: "Magnificent", description: "When something is awesome. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", shown: false)) self.words.append(Word(id: 0, name: "Magnificent", description: "When something is awesome. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", shown: false))
self.words.append(Word(id: 1, name: "Mesmerising", description: "When something is beautiful", shown: false)) self.words.append(Word(id: 1, name: "Mesmerising", description: "When something is beautiful", shown: false))

View File

@@ -22,32 +22,36 @@ class WordAXModelView: ObservableObject {
let words = model.words let words = model.words
if words.count > 0 { if words.count > 0 {
let notShownWords = words.filter({!$0.shown})
if notShownWords.count == 0 {
return nil
}
// if today is the date they're supposed to be shown // if today is the date they're supposed to be shown
let displayToday = words.filter({ $0.lastSeenOn != nil && $0.lastSeenOn!.addSpacedRepetitionMilestone(milestone: $0.nextSpacedRepetitionMilestone!).isBeforeTodayOrToday()})
let displayToday = words.filter({ $0.lastSeenOn != nil && $0.lastSeenOn!.addSpacedRepetitionMilestone(milestone: $0.nextSpacedRepetitionMilestone!).isAfterTodayOrToday()})
if displayToday.count > 0 { if displayToday.count > 0 {
return displayToday.first! return displayToday.first!
} }
// first word ever shown // first word ever shown
let shownWords = words.filter({ $0.shown }) // let shownWords = words.filter({ $0.shown })
if shownWords.count == 0 { // if shownWords.count == 0 {
return words.first! return notShownWords.sorted(by: {$0.id < $1.id}).first
} // }
// if today is the day to show a new word // if today is the day to show a new word
let settings = model.settings // let settings = model.settings
if shownWords.count == 0 || // if shownWords.count == 0 ||
settings.lastShownNew == nil || // settings.lastShownNew == nil ||
settings.lastShownNew!.addFrequency(frequency: settings.frequency).isAfterToday() { // settings.lastShownNew!.addFrequency(frequency: settings.frequency).isAfterToday() {
return words.first! // return words.first!
} // }
} }
// otherwise show nothing // otherwise show nothing
return nil return nil
} }
public func setSpacedRepetitionMilestone(wordId: Int, milestone: WordAX.SpacedRepetitionMilestoneEnum?) { public func ankiButtonClicked(wordId: Int, milestone: WordAX.SpacedRepetitionMilestoneEnum?) {
model.setSpacedRepetitionMilestone(wordId: wordId, milestone: milestone) model.setSpacedRepetitionMilestone(wordId: wordId, milestone: milestone)
model.wordShown(wordId: wordId)
} }
} }
@@ -72,6 +76,12 @@ extension Date {
return selfDate.year! > paramDate.year! || selfDate.month! > paramDate.month! || selfDate.day! > paramDate.day! return selfDate.year! > paramDate.year! || selfDate.month! > paramDate.month! || selfDate.day! > paramDate.day!
} }
func isBefore(_ date: Date) -> Bool {
let selfDate = getOnlyDate(date: self)
let paramDate = getOnlyDate(date: date)
return selfDate.year! < paramDate.year! || selfDate.month! < paramDate.month! || selfDate.day! < paramDate.day!
}
func addFrequency(frequency: WordAX.FrequencyEnum) -> Date { func addFrequency(frequency: WordAX.FrequencyEnum) -> Date {
self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60)) self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60))
} }
@@ -84,7 +94,11 @@ extension Date {
self.isAfter(Date()) self.isAfter(Date())
} }
func isAfterTodayOrToday() -> Bool { func isBeforeToday() -> Bool {
self.isAfterToday() || self.isToday() self.isBefore(Date())
}
func isBeforeTodayOrToday() -> Bool {
self.isBeforeToday() || self.isToday()
} }
} }

View File

@@ -21,7 +21,8 @@ struct WordView: View {
.bold() .bold()
VStack { VStack {
if word.shown && word.lastSeenOn != nil { if word.shown && word.lastSeenOn != nil {
Text(model.getDateFormatter().string(from: word.lastSeenOn!)) Text("Last seen: " + model.getDateFormatter().string(from: word.lastSeenOn!))
.font(.subheadline)
} }
if showDescription { if showDescription {
wordText wordText