feat(client): ConsideringIndicator — rotates think-lines on a Timer

This commit is contained in:
2026-07-10 15:06:31 -05:00
parent 6bd5e4f84a
commit 82b2de19bb
2 changed files with 63 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
class_name ConsideringIndicator
extends Node
## Thin node shim (charter §13). While a call is in flight it rotates an authored
## ConsideringPhrases line onto a Label every ROTATE_SECONDS, reframing the wait
## as the GM thinking. The phrase logic is the pure, tested ConsideringPhrases;
## the Timer/tree wiring here is the untested shim (verified by running the
## harness). One instance persists on the harness so the rotation index is not
## reset per call (spec decision 4).
const ROTATE_SECONDS := 2.0
var _phrases: ConsideringPhrases
var _timer: Timer
var _label: Label
func _init(phrases: ConsideringPhrases = null) -> void:
_phrases = phrases if phrases != null else ConsideringPhrases.new()
func _ready() -> void:
_timer = Timer.new()
_timer.wait_time = ROTATE_SECONDS
_timer.one_shot = false
_timer.timeout.connect(_advance)
add_child(_timer)
func start(label: Label) -> void:
_label = label
_advance() # show a phrase immediately, don't wait ROTATE_SECONDS
_timer.start()
func stop() -> void:
_timer.stop()
if _label != null:
_label.text = ""
_label = null
func _advance() -> void:
if _label != null:
_label.text = _phrases.next()

View File

@@ -0,0 +1,19 @@
extends "res://addons/gut/test.gd"
const ConsideringIndicator = preload("res://scripts/ui/considering_indicator.gd")
const ConsideringPhrases = preload("res://scripts/ui/considering_phrases.gd")
func test_start_shows_first_phrase_and_stop_clears():
# Point phrases at a missing file so next() is deterministically LAST_RESORT.
var phrases = ConsideringPhrases.new("res://content/does_not_exist.json")
var ind = ConsideringIndicator.new(phrases)
add_child_autofree(ind) # _ready() creates the Timer child
var label := Label.new()
add_child_autofree(label)
ind.start(label)
assert_eq(label.text, ConsideringPhrases.LAST_RESORT) # first phrase shown at once
ind.stop()
assert_eq(label.text, "") # cleared on stop