When countdown finishes, fetch requests reload
This commit is contained in:
@@ -56,6 +56,7 @@ Why settle for pricey apps when you can have WordAX? We're here to prove that ef
|
|||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
- [ ] Anki card "store" - download any anki flashcards you want from the online store that already exists somewhere
|
- [ ] Anki card "store" - download any anki flashcards you want from the online store that already exists somewhere
|
||||||
|
- [ ] Export your anki to the store?
|
||||||
- [ ] Import anki cards in the .anki format
|
- [ ] Import anki cards in the .anki format
|
||||||
- [x] Create flashcards
|
- [x] Create flashcards
|
||||||
- [ ] Add tags to cards
|
- [ ] Add tags to cards
|
||||||
@@ -65,8 +66,7 @@ Why settle for pricey apps when you can have WordAX? We're here to prove that ef
|
|||||||
- [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?
|
||||||
- [ ] Add some animations?
|
- [ ] Add some animations?
|
||||||
- [ ] Implement logic
|
- [x] Implement logic
|
||||||
- [ ] Export your anki to the store?
|
|
||||||
- [ ] Make an apple watch version of the app
|
- [ ] Make an apple watch version of the app
|
||||||
|
|
||||||
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|||||||
@@ -120,6 +120,9 @@ extension Int {
|
|||||||
// else {
|
// else {
|
||||||
// result = "\(self)"
|
// result = "\(self)"
|
||||||
// }
|
// }
|
||||||
|
if days == 0 && hours == 0 && minutes == 0 {
|
||||||
|
return "\(seconds)s"
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class Flashcard: NSManagedObject {
|
|||||||
}
|
}
|
||||||
let milestoneIndex = sorted.firstIndex(where: {$0.rawValue == milestone!.rawValue})!
|
let milestoneIndex = sorted.firstIndex(where: {$0.rawValue == milestone!.rawValue})!
|
||||||
if milestoneIndex < sorted.count {
|
if milestoneIndex < sorted.count {
|
||||||
|
// 1 minute is only if answer was wrong, so 10 minutes is the first valid milestone
|
||||||
return sorted[milestoneIndex + 1] == .OneMinute ? .TenMinutes : sorted[milestoneIndex + 1]
|
return sorted[milestoneIndex + 1] == .OneMinute ? .TenMinutes : sorted[milestoneIndex + 1]
|
||||||
}
|
}
|
||||||
return .OneYear
|
return .OneYear
|
||||||
@@ -47,7 +48,6 @@ public class Flashcard: NSManagedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum {
|
func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum {
|
||||||
let milestone = SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone)
|
SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone)
|
||||||
return milestone == .OneMinute ? .TenMinutes : milestone
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,30 +9,12 @@ import SwiftUI
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
struct AnkiView: View {
|
struct AnkiView: View {
|
||||||
// @EnvironmentObject var model: WordAXModelView
|
|
||||||
@Environment(\.managedObjectContext) var moc
|
@Environment(\.managedObjectContext) var moc
|
||||||
|
|
||||||
// get flashcards to display
|
|
||||||
// @FetchRequest(sortDescriptors: [
|
|
||||||
// NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false),
|
|
||||||
// NSSortDescriptor(key: "lastSeenOn", ascending: true)
|
|
||||||
// ], predicate: NSCompoundPredicate(type: .or, subpredicates: [
|
|
||||||
// NSCompoundPredicate(type: .and, subpredicates: [
|
|
||||||
// NSPredicate(format: "%K != nil", "lastSeenOn"),
|
|
||||||
// NSPredicate(format: "lastSeenOn + nextSpacedRepetitionMilestone < %@", Date() as CVarArg)
|
|
||||||
// ]),
|
|
||||||
// NSPredicate(format: "lastSeenOn == nil")
|
|
||||||
// ])) var flashcards: FetchedResults<Flashcard>
|
|
||||||
|
|
||||||
// get the most recent flashcard
|
|
||||||
// @FetchRequest(sortDescriptors: [],
|
|
||||||
// predicate: NSPredicate(format: "%K != nil", "lastSeenOn")) var soonestFlashcard: FetchedResults<Flashcard>
|
|
||||||
|
|
||||||
@State private var timeRemaining = 10
|
@State private var timeRemaining = 10
|
||||||
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
|
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
|
||||||
@State var flashcards: [Flashcard] = []
|
@State var flashcards: [Flashcard] = []
|
||||||
@State var sortedFlashcards: [Flashcard] = []
|
@State var soonestFlashcards: [Flashcard] = []
|
||||||
@State var soonestFlashcard: [Flashcard] = []
|
|
||||||
@State var showDescription = false
|
@State var showDescription = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -47,13 +29,13 @@ struct AnkiView: View {
|
|||||||
// Text("How did you do?")
|
// Text("How did you do?")
|
||||||
// .font(.subheadline)
|
// .font(.subheadline)
|
||||||
// .foregroundStyle(.gray)
|
// .foregroundStyle(.gray)
|
||||||
ButtonHStackView(flashcard: flashcards.first!, geometry: geometry, showDescription: $showDescription)
|
ButtonHStackView(flashcard: flashcards.first!, geometry: geometry, reload: refreshFlashcards, showDescription: $showDescription)
|
||||||
.padding([.bottom, .trailing, .leading])
|
.padding([.bottom, .trailing, .leading])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !soonestFlashcard.isEmpty {
|
if !soonestFlashcards.isEmpty {
|
||||||
Group {
|
Group {
|
||||||
Text("Next flashcard in: \(timeRemaining.convertDurationSecondsToCountdown())")
|
Text("Next flashcard in: \(timeRemaining.convertDurationSecondsToCountdown())")
|
||||||
.foregroundStyle(.black)
|
.foregroundStyle(.black)
|
||||||
@@ -63,15 +45,6 @@ struct AnkiView: View {
|
|||||||
.clipShape(.buttonBorder)
|
.clipShape(.buttonBorder)
|
||||||
.padding(.vertical, 50)
|
.padding(.vertical, 50)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.onAppear {
|
|
||||||
if !soonestFlashcard.isEmpty {
|
|
||||||
sortedFlashcards = soonestFlashcard.sorted(by: {
|
|
||||||
($0.lastSeenOn!.addSpacedRepetitionMilestone(milestone:$0.getSpacedRepetitionMilestone()).timeIntervalSinceNow) < ($1.lastSeenOn!.addSpacedRepetitionMilestone(milestone: $1.getSpacedRepetitionMilestone()).timeIntervalSinceNow)
|
|
||||||
})
|
|
||||||
timeRemaining = Int(sortedFlashcards.first!.lastSeenOn!.addSpacedRepetitionMilestone(milestone:sortedFlashcards.first!.getSpacedRepetitionMilestone()).timeIntervalSinceNow)
|
|
||||||
}
|
|
||||||
refreshFlashcards()
|
|
||||||
}
|
|
||||||
.onReceive(timer) { time in
|
.onReceive(timer) { time in
|
||||||
if timeRemaining > 1 {
|
if timeRemaining > 1 {
|
||||||
timeRemaining -= 1
|
timeRemaining -= 1
|
||||||
@@ -103,32 +76,50 @@ struct AnkiView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func refreshFlashcards() {
|
func refreshFlashcards() {
|
||||||
let request = NSFetchRequest<Flashcard>(entityName: "Flashcard")
|
let requestAllFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard")
|
||||||
request.predicate = NSCompoundPredicate(type: .or, subpredicates: [
|
requestAllFlashcards.predicate = 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")
|
||||||
])
|
])
|
||||||
request.sortDescriptors = [
|
requestAllFlashcards.sortDescriptors = [
|
||||||
NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false),
|
NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false),
|
||||||
NSSortDescriptor(key: "lastSeenOn", ascending: true)
|
NSSortDescriptor(key: "lastSeenOn", ascending: true)
|
||||||
]
|
]
|
||||||
do {
|
do {
|
||||||
flashcards = try moc.fetch(request)
|
flashcards = try moc.fetch(requestAllFlashcards)
|
||||||
} catch {
|
} catch {
|
||||||
print("Something went wroooong")
|
print("Something went wrong while fetching available flashcards")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let req = NSFetchRequest<Flashcard>(entityName: "Flashcard")
|
let requestSoonestFlashcards = NSFetchRequest<Flashcard>(entityName: "Flashcard")
|
||||||
req.predicate = NSPredicate(format: "%K != nil", "lastSeenOn")
|
requestSoonestFlashcards.predicate = NSPredicate(format: "%K != nil", "lastSeenOn")
|
||||||
do {
|
do {
|
||||||
soonestFlashcard = try moc.fetch(request)
|
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 bum")
|
print("Something went wrong while fetching latest flashcard")
|
||||||
|
}
|
||||||
|
if !soonestFlashcards.isEmpty {
|
||||||
|
soonestFlashcards = soonestFlashcards.sorted {
|
||||||
|
if $0.lastSeenOn != nil && $1.lastSeenOn != nil {
|
||||||
|
return $0.lastSeenOn!.addSpacedRepetitionMilestone(milestone:$0.getSpacedRepetitionMilestone()).timeIntervalSinceNow < $1.lastSeenOn!.addSpacedRepetitionMilestone(milestone: $1.getSpacedRepetitionMilestone()).timeIntervalSinceNow
|
||||||
|
} else {
|
||||||
|
return $0.lastSeenOn != nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if soonestFlashcards.first!.lastSeenOn != nil {
|
||||||
|
timeRemaining = Int(soonestFlashcards.first!.lastSeenOn!.addSpacedRepetitionMilestone(milestone:soonestFlashcards.first!.getSpacedRepetitionMilestone()).timeIntervalSinceNow.rounded())
|
||||||
|
} else {
|
||||||
|
print("Something went wrong while getting latest flashcard")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import SwiftUI
|
|||||||
struct ButtonHStackView: View {
|
struct ButtonHStackView: View {
|
||||||
let flashcard: Flashcard
|
let flashcard: Flashcard
|
||||||
let geometry: GeometryProxy
|
let geometry: GeometryProxy
|
||||||
|
let reload: () -> Void
|
||||||
@Binding var showDescription: Bool
|
@Binding var showDescription: Bool
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
@@ -21,6 +22,7 @@ struct ButtonHStackView: View {
|
|||||||
color: .red,
|
color: .red,
|
||||||
geometry: geometry,
|
geometry: geometry,
|
||||||
timeText: DataController.SpacedRepetitionMilestoneEnum.OneMinute.rawValue.convertDurationSecondsToString(),
|
timeText: DataController.SpacedRepetitionMilestoneEnum.OneMinute.rawValue.convertDurationSecondsToString(),
|
||||||
|
reload: reload,
|
||||||
showDescription: $showDescription
|
showDescription: $showDescription
|
||||||
)
|
)
|
||||||
NextRepetitionButtonView(
|
NextRepetitionButtonView(
|
||||||
@@ -30,6 +32,7 @@ struct ButtonHStackView: View {
|
|||||||
color: .orange,
|
color: .orange,
|
||||||
geometry: geometry,
|
geometry: geometry,
|
||||||
timeText: flashcard.getSpacedRepetitionMilestone().rawValue.convertDurationSecondsToString(),
|
timeText: flashcard.getSpacedRepetitionMilestone().rawValue.convertDurationSecondsToString(),
|
||||||
|
reload: reload,
|
||||||
showDescription: $showDescription
|
showDescription: $showDescription
|
||||||
)
|
)
|
||||||
NextRepetitionButtonView(
|
NextRepetitionButtonView(
|
||||||
@@ -39,6 +42,7 @@ struct ButtonHStackView: View {
|
|||||||
color: .green,
|
color: .green,
|
||||||
geometry: geometry,
|
geometry: geometry,
|
||||||
timeText: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard.getSpacedRepetitionMilestone()).rawValue.convertDurationSecondsToString(),
|
timeText: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard.getSpacedRepetitionMilestone()).rawValue.convertDurationSecondsToString(),
|
||||||
|
reload: reload,
|
||||||
showDescription: $showDescription
|
showDescription: $showDescription
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ struct NextRepetitionButtonView: View {
|
|||||||
let color: Color
|
let color: Color
|
||||||
let geometry: GeometryProxy
|
let geometry: GeometryProxy
|
||||||
let timeText: String
|
let timeText: String
|
||||||
|
let reload: () -> Void
|
||||||
@Environment(\.managedObjectContext) var moc
|
@Environment(\.managedObjectContext) var moc
|
||||||
// { colorScheme == .light ? .cyan : .darkCyan }
|
// { colorScheme == .light ? .cyan : .darkCyan }
|
||||||
@Binding var showDescription: Bool
|
@Binding var showDescription: Bool
|
||||||
@@ -34,6 +35,7 @@ struct NextRepetitionButtonView: View {
|
|||||||
print("Something went wrong while saving the flashcard info: \(error.localizedDescription)")
|
print("Something went wrong while saving the flashcard info: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
self.showDescription = false
|
self.showDescription = false
|
||||||
|
reload()
|
||||||
}) {
|
}) {
|
||||||
VStack {
|
VStack {
|
||||||
Text(buttonText)
|
Text(buttonText)
|
||||||
|
|||||||
Reference in New Issue
Block a user