Rebuild flashcard study screen from mockup, with real backend-backed stats
Study screen now matches the provided mockup's layout: a "Current Deck" panel with a circular mastery-progress ring, and a "Spaced Repetition" panel (New/Due/Learning/Review counts, streak, daily goal) on either side of the card. Kept the app's real global sidebar rather than the mockup's own nav, per direction. Mastery/Streak/Daily Goal weren't tracked anywhere, so this adds real backend support rather than showing fabricated numbers: - Mastered = graduated to review state AND FSRS stability >= 21 days (FlashcardScheduleStore.MasteryStabilityDaysThreshold), stricter than the plain Review-state count - CurrentStreakDays = consecutive UTC days with a review, computed from review-log timestamps in the new pure FlashcardScheduling .ComputeStreakDays (unit tested, habit-streak semantics: doesn't reset to 0 the instant a new day starts before today's first review) - DailyGoal/ReviewsToday reuse the account's existing ReviewsPerDay setting rather than inventing a new one Also removes the exit "X" button in favor of the same Escape/pause menu the question-player flow uses (main.gd's shared app_menu, with an "Exit Study Session" action), and adds a new circular_progress.gd reusable ring control plus a real "Options" menu (bury/suspend the current card) wired to schedule endpoints that had no UI before.
This commit is contained in:
+10
-3
@@ -717,7 +717,7 @@ func _input(event: InputEvent) -> void:
|
||||
_close_account_menu()
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
if current_screen_name in ["player", "ccs_player"]:
|
||||
if current_screen_name in ["player", "ccs_player", "flashcards_study"]:
|
||||
_toggle_app_menu()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
@@ -895,9 +895,13 @@ func _toggle_app_menu() -> void:
|
||||
app_menu.visible = true
|
||||
app_menu.size = app_menu.custom_minimum_size
|
||||
app_menu.position = (get_viewport_rect().size - app_menu.size) * 0.5
|
||||
menu_exit_button.visible = (current_screen_name == "player" and BlockSessionService.block_started) or current_screen_name == "ccs_player"
|
||||
menu_exit_button.visible = (current_screen_name == "player" and BlockSessionService.block_started) or current_screen_name in ["ccs_player", "flashcards_study"]
|
||||
if menu_exit_button.visible:
|
||||
menu_exit_button.text = "Leave Case" if current_screen_name == "ccs_player" else "Leave (timer continues)" if BlockSessionService.session_kind == "simulation" else "Exit Run"
|
||||
menu_exit_button.text = (
|
||||
"Leave Case" if current_screen_name == "ccs_player"
|
||||
else "Exit Study Session" if current_screen_name == "flashcards_study"
|
||||
else "Leave (timer continues)" if BlockSessionService.session_kind == "simulation"
|
||||
else "Exit Run")
|
||||
Style.style_chip(menu_exit_button, Style.AMBER)
|
||||
if current_screen_name == "player": BlockSessionService.pause_current_question_timer()
|
||||
|
||||
@@ -914,6 +918,9 @@ func _exit_run() -> void:
|
||||
var ccs_player = screens.get("ccs_player")
|
||||
if ccs_player != null and ccs_player.has_method("leave_case"): ccs_player.leave_case()
|
||||
return
|
||||
if current_screen_name == "flashcards_study":
|
||||
show_screen("flashcards_hub")
|
||||
return
|
||||
var was_core_run := BlockSessionService.session_kind == "core"
|
||||
var was_review_run := BlockSessionService.session_kind == "review"
|
||||
if BlockSessionService.block_started and BlockSessionService.session_kind != "simulation":
|
||||
|
||||
Reference in New Issue
Block a user