fix(ui): toggle stays clickable during battery suspend — D-138 player autonomy

Player autonomy wins: AI Dialogue toggle is only greyed out for RAM fail
(< 1.6 GB free). Battery suspend shows a warning label instead of
disabling the toggle — player can override the auto-suspend at any time.

Changes:
- settings_dialog: toggle disabled = hw_status == "fail" only
- settings_dialog: add _ai_battery_warning_label (STATUS_YELLOW) shown
  when _ai_inference_suspended; hidden when plugged back in via
  set_ai_inference_suspended()
- settings_dialog: is_ai_dialogue_toggle_enabled() no longer checks
  _ai_inference_suspended
- settings_dialog: set_ai_inference_suspended() updates warning label
  visibility, not toggle disabled state
- ui-strings: add settings.ai_battery_warning "High battery usage"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 10:49:06 +01:00
co-authored by Claude Sonnet 4.6
parent 12d25ce17f
commit 41d16d01ae
2 changed files with 19 additions and 9 deletions
+1
View File
@@ -199,6 +199,7 @@ settings:
ai_dialogue_toggle: "AI-Enhanced Dialogue"
ai_status_checking: "Speed not yet measured — will check on first enable."
ai_status_ram_marginal: "Low memory — performance may vary."
ai_battery_warning: "High battery usage"
# ============================================================
# CHARACTER SELECTION (if applicable in v0.1)
+18 -9
View File
@@ -37,6 +37,7 @@ var _container: VBoxContainer = null
var _ai_hw_status: String = "" # "pass" | "marginal" | "fail" | "" (not yet checked)
var _ai_check_node: CheckButton = null
var _ai_inference_suspended: bool = false # D-138 §8 Layer 3 battery auto-suspend state
var _ai_battery_warning_label: Label = null # shown when on battery; toggle stays enabled
signal closed
signal debug_console_toggled(enabled: bool) # #581: debug console enabled/disabled
@@ -214,7 +215,7 @@ func _build_ui() -> void:
_ai_check_node = CheckButton.new()
_ai_check_node.button_pressed = GameState.ai_enhanced_dialogue_enabled
_ai_check_node.disabled = (_ai_hw_status == "fail") or _ai_inference_suspended
_ai_check_node.disabled = (_ai_hw_status == "fail")
ai_hbox.add_child(_ai_check_node)
# Status message label — only shown when non-empty
@@ -235,6 +236,14 @@ func _build_ui() -> void:
ai_status_label.visible = not status_msg.is_empty()
_container.add_child(ai_status_label)
# Battery warning label — visible when on battery power; toggle stays enabled per D-138.
_ai_battery_warning_label = Label.new()
_ai_battery_warning_label.text = UIStrings.get_text("settings.ai_battery_warning")
_ai_battery_warning_label.add_theme_font_size_override("font_size", FONT_SIZE_SMALL)
_ai_battery_warning_label.add_theme_color_override("font_color", STATUS_YELLOW)
_ai_battery_warning_label.visible = _ai_inference_suspended
_container.add_child(_ai_battery_warning_label)
_ai_check_node.toggled.connect(func(enabled: bool) -> void:
GameState.ai_enhanced_dialogue_enabled = enabled
_save_ai_pref(enabled)
@@ -271,7 +280,8 @@ func _destroy_ui() -> void:
if _container:
_container.queue_free()
_container = null
_ai_check_node = null # freed with _container
_ai_check_node = null # freed with _container
_ai_battery_warning_label = null
# -- #646: AI Dialogue testable API -------------------------------------------
@@ -293,9 +303,9 @@ func set_ai_dialogue_hardware_status(status: String) -> void:
## Returns true if the AI-Enhanced Dialogue toggle is currently enabled (not greyed out).
## Disabled by RAM "fail" OR by active battery suspension (D-138 §8 Layer 3).
## Only disabled by RAM "fail" battery suspension shows a warning but never greys the toggle.
func is_ai_dialogue_toggle_enabled() -> bool:
return _ai_hw_status != "fail" and not _ai_inference_suspended
return _ai_hw_status != "fail"
## Returns true if AI inference is currently auto-suspended due to battery power (D-138 §8 Layer 3).
@@ -305,14 +315,13 @@ func is_ai_inference_suspended() -> bool:
## Update battery suspension display state.
## Shows/hides the battery warning label; toggle stays enabled — player autonomy wins (D-138).
## Called when PlatformInfo.power_profile_changed fires (via main.gd or HardwareDetector).
## Tests can inject suspended=true to verify UI reacts correctly.
## Tests can inject suspended=true to verify the warning label appears.
func set_ai_inference_suspended(suspended: bool) -> void:
_ai_inference_suspended = suspended
# If the dialog is currently open and built, update the status label to reflect suspension.
# The next open() call will rebuild from scratch with the correct state anyway.
if _ai_check_node != null:
_ai_check_node.disabled = suspended or (_ai_hw_status == "fail")
if _ai_battery_warning_label != null:
_ai_battery_warning_label.visible = suspended
## Persist the AI Dialogue enabled state to the local prefs file.