Polish question player header/toolbar and add configurable block size

- Fix the toolbar wrapping onto two rows: its minimum width was tuned
  for an older, narrower button set and never widened back out after
  reverting to bare icon buttons.
- Drop the "Time elapsed"/"Ctrl+Enter" readout next to Submit - it was
  clutter; the underlying timer logic keeps running unseen.
- Move the RanaZe brand mark above the question-count row instead of
  sharing a line with it.
- Progress text drops the word "Question" everywhere ("1 of 10"), and
  core/dynamic sessions now cycle against a configurable block size
  (Settings > Question block size, default 10) instead of counting up
  forever.
This commit is contained in:
hz
2026-07-24 21:57:03 -05:00
parent 62e65fd22c
commit 50f54b1bec
3 changed files with 87 additions and 22 deletions
+31
View File
@@ -28,10 +28,41 @@ var simulation_block_index := 0
var simulation_total_blocks := 12
var simulation_deadline_unix := 0.0
var review_first_submission_recorded := false
var core_block_size := DEFAULT_CORE_BLOCK_SIZE
const CORE_MIN_TARGET_SECONDS := 45.0
const CORE_MAX_TARGET_SECONDS := 150.0
const CORE_RETRY_TARGET_SECONDS := 30.0
const DEFAULT_CORE_BLOCK_SIZE := 10
const CORE_BLOCK_SIZE_MIN := 5
const CORE_BLOCK_SIZE_MAX := 40
const SETTINGS_PATH := "user://settings.cfg"
const SETTINGS_SECTION := "session"
const SETTINGS_KEY_CORE_BLOCK_SIZE := "core_block_size"
func _ready() -> void:
_load_core_block_size()
func set_core_block_size(value: int) -> void:
var clamped := clampi(value, CORE_BLOCK_SIZE_MIN, CORE_BLOCK_SIZE_MAX)
if clamped == core_block_size:
return
core_block_size = clamped
var config := ConfigFile.new()
config.load(SETTINGS_PATH)
config.set_value(SETTINGS_SECTION, SETTINGS_KEY_CORE_BLOCK_SIZE, core_block_size)
if config.save(SETTINGS_PATH) != OK:
push_warning("Unable to save core question block size preference.")
func _load_core_block_size() -> void:
var config := ConfigFile.new()
if config.load(SETTINGS_PATH) == OK:
core_block_size = clampi(
int(config.get_value(SETTINGS_SECTION, SETTINGS_KEY_CORE_BLOCK_SIZE, DEFAULT_CORE_BLOCK_SIZE)),
CORE_BLOCK_SIZE_MIN, CORE_BLOCK_SIZE_MAX)
func start_dynamic_question(question: Dictionary) -> bool:
+15 -22
View File
@@ -221,13 +221,10 @@ func _ready() -> void:
header_stack = VBoxContainer.new()
header_stack.add_theme_constant_override("separation", 8)
card_content.add_child(header_stack)
header_row = HBoxContainer.new()
header_row.add_theme_constant_override("separation", 16)
header_stack.add_child(header_row)
var header_brand := HBoxContainer.new()
header_brand.add_theme_constant_override("separation", 8)
header_row.add_child(header_brand)
header_stack.add_child(header_brand)
var header_brand_mark := TextureRect.new()
header_brand_mark.texture = Brand.ranaze_mark_texture()
header_brand_mark.custom_minimum_size = Vector2(28, 28)
@@ -240,6 +237,10 @@ func _ready() -> void:
header_wordmark_label.add_theme_font_size_override("font_size", 18)
header_brand.add_child(header_wordmark_label)
header_row = HBoxContainer.new()
header_row.add_theme_constant_override("separation", 16)
header_stack.add_child(header_row)
var progress_group := VBoxContainer.new()
progress_group.add_theme_constant_override("separation", 2)
progress_group.size_flags_vertical = Control.SIZE_SHRINK_CENTER
@@ -660,15 +661,13 @@ func _ready() -> void:
bottom_progress_bar.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
bottom_progress_group.add_child(bottom_progress_bar)
var time_group := VBoxContainer.new()
time_group.add_theme_constant_override("separation", 0)
actions.add_child(time_group)
# The timer readout still runs (BlockSessionService pacing/scoring depends on
# it, and _update_timer_bar keeps its text current), it's just no longer
# parented into the bottom bar - the caption + digits and the "Ctrl+Enter"
# hint were clutter next to the Submit button.
timer_caption_label = Label.new()
timer_caption_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
_set_scaled_label(timer_caption_label, 12, Brand.SLATE)
time_group.add_child(timer_caption_label)
time_group.add_child(timer_label)
next_button = Button.new()
next_button.text = "Submit Block" if BlockSessionService.session_kind == "simulation" and BlockSessionService.current_index + 1 == BlockSessionService.active_questions.size() else "Next" if BlockSessionService.session_kind == "simulation" else "Submit"
@@ -678,12 +677,6 @@ func _ready() -> void:
next_button.pressed.connect(_submit_or_next)
actions.add_child(next_button)
var shortcut_hint_label := Label.new()
shortcut_hint_label.name = "SubmitShortcutHint"
shortcut_hint_label.text = "⌘ Enter" if OS.get_name() == "macOS" else "Ctrl+Enter"
_set_scaled_label(shortcut_hint_label, 11, Brand.SLATE)
actions.add_child(shortcut_hint_label)
timer_footer = HBoxContainer.new()
timer_footer.add_theme_constant_override("separation", 12)
card_content.add_child(timer_footer)
@@ -793,7 +786,9 @@ func _refresh_responsive_layout() -> void:
header_toolbar_host.reparent(target_parent)
header_toolbar_host.size_flags_horizontal = Control.SIZE_EXPAND_FILL if compact else Control.SIZE_SHRINK_END
question_toolbar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
header_toolbar_host.custom_minimum_size.x = 0.0 if compact else 520.0
# 11 bare 44px icon buttons + the wider 92px Feedback button, with 8px gaps
# between all 12 - anything less than this wraps onto a second row.
header_toolbar_host.custom_minimum_size.x = 0.0 if compact else 680.0
if size.x < 560.0:
nav_palette.columns = 5
else:
@@ -1074,9 +1069,6 @@ func _apply_question_theme() -> void:
skip_button.add_theme_color_override("font_color", skip_link_color)
skip_button.add_theme_color_override("font_hover_color", skip_link_color)
skip_button.add_theme_color_override("font_disabled_color", Brand.muted_color(dark))
var shortcut_hint := find_child("SubmitShortcutHint", true, false) as Label
if shortcut_hint != null:
shortcut_hint.add_theme_color_override("font_color", Brand.muted_color(dark))
if next_button != null:
next_button.add_theme_stylebox_override("normal", _primary_action_box(dark, "normal"))
next_button.add_theme_stylebox_override("hover", _primary_action_box(dark, "hover"))
@@ -2078,8 +2070,9 @@ func _is_session_timer_visible() -> bool:
func _question_progress_text() -> String:
if BlockSessionService.session_kind == "core":
return "Question %d" % (BlockSessionService.core_answer_count + 1)
return "Question %d of %d" % [
var block_size := BlockSessionService.core_block_size
return "%d of %d" % [(BlockSessionService.core_answer_count % block_size) + 1, block_size]
return "%d of %d" % [
mini(BlockSessionService.current_index + 1, BlockSessionService.active_questions.size()),
BlockSessionService.active_questions.size()
]
+41
View File
@@ -4,12 +4,14 @@ const Brand := preload("res://scripts/ui/medmind_style.gd")
const QUESTION_TEXT_SCALE_MIN := 0.85
const QUESTION_TEXT_SCALE_MAX := 1.35
const QUESTION_TEXT_SCALE_STEP := 0.1
const CORE_BLOCK_SIZE_STEP := 5
var main: Control
var theme_toggle: CheckButton
var sound_toggle: CheckButton
var question_scale_value_label: Label
var ccs_scale_value_label: Label
var core_block_size_value_label: Label
func _ready() -> void:
@@ -59,6 +61,7 @@ func _ready() -> void:
content.add_child(_build_text_scale_row("Question bank text size", "question"))
content.add_child(_build_text_scale_row("CCS case text size", "ccs"))
content.add_child(_build_core_block_size_row())
var legal_panel := PanelContainer.new()
legal_panel.custom_minimum_size = Vector2(520, 0)
@@ -131,6 +134,42 @@ func _build_text_scale_row(label_text: String, kind: String) -> HBoxContainer:
return row
func _build_core_block_size_row() -> HBoxContainer:
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(0, 52)
row.add_theme_constant_override("separation", 12)
var label := Label.new()
label.text = "Question block size"
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
row.add_child(label)
var smaller := Button.new()
smaller.text = "-"
smaller.tooltip_text = "Fewer questions per block"
smaller.custom_minimum_size = Vector2(44, 44)
smaller.pressed.connect(_adjust_core_block_size.bind(-CORE_BLOCK_SIZE_STEP))
row.add_child(smaller)
core_block_size_value_label = Label.new()
core_block_size_value_label.custom_minimum_size = Vector2(56, 0)
core_block_size_value_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
row.add_child(core_block_size_value_label)
var larger := Button.new()
larger.text = "+"
larger.tooltip_text = "More questions per block"
larger.custom_minimum_size = Vector2(44, 44)
larger.pressed.connect(_adjust_core_block_size.bind(CORE_BLOCK_SIZE_STEP))
row.add_child(larger)
return row
func _adjust_core_block_size(delta: int) -> void:
BlockSessionService.set_core_block_size(BlockSessionService.core_block_size + delta)
_refresh_text_scale_labels()
func _adjust_question_text_scale(delta: float) -> void:
var current: float = AccountProfileService.preferences.get("questionTextScale", 1.0)
var next_scale: float = clamp(current + delta, QUESTION_TEXT_SCALE_MIN, QUESTION_TEXT_SCALE_MAX)
@@ -149,6 +188,8 @@ func _refresh_text_scale_labels() -> void:
question_scale_value_label.text = "%d%%" % round(question_scale * 100)
if ccs_scale_value_label != null:
ccs_scale_value_label.text = "%d%%" % round(CCSService.text_scale * 100)
if core_block_size_value_label != null:
core_block_size_value_label.text = str(BlockSessionService.core_block_size)
func _on_theme_toggled(enabled: bool) -> void: