Files
settled-reach/client/ui/implant/implant_app.gd
T
jpmschweitzerandClaude Opus 4.6 ea7bcfabfb fix(ui): PR #131 review round 3 — nits sweep
Seven nit-level fixes from PR review:

- Remove dead signal insert_deactivated from ImplantApp; the hook method
  on_insert_deactivated() is the actual contract.
- Rewrite _on_atlas_economics_link comment in main.gd to reflect the
  actual flow (AtlasApp closes as a consequence of HudGroups single-
  active-app, not before emitting anything).
- Document the "pop never empties below default" invariant on
  ImplantNavStack.pop() with a pointer to reset_to_default.
- Add _mutating re-entrancy guard on ImplantNavStack mutation methods.
  push_error + early return if called during a screen_changed emission.
- main.gd registry loop now uses typed ImplantAppManifest property
  access (manifest.app_path, manifest.default_key) instead of
  dictionary-style .get() calls. Empty app_path triggers push_warning.
- Document the economics [/] hotkey exception in main.gd and reference
  the planned handle_global_key lifecycle hook. Arch doc Follow-up
  section gains a bullet for the new hook.
- Comment the independent-version-read rationale above client_ver and
  proto_ver in loading_screen.gd.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 14:47:05 +02:00

90 lines
1.9 KiB
GDScript

class_name ImplantApp
extends Control
## Base class for all implant apps. Absorbs HudGroups boilerplate; subclasses
## override lifecycle hooks only (#844, D-191).
##
## Subclass _ready() pattern:
## func _ready() -> void:
## manifest = load("res://ui/implant/apps/my_app/app.tres")
## super._ready()
## # additional init here if needed
signal app_opened(mode: int)
signal app_closed
var manifest: ImplantAppManifest = null
var nav: ImplantNavStack = null
func _ready() -> void:
set_anchors_preset(Control.PRESET_FULL_RECT)
mouse_filter = Control.MOUSE_FILTER_STOP
visible = false
if manifest:
HudGroups.register(self, manifest.app_path)
HudGroups.app_changed.connect(_internal_app_changed)
nav = ImplantNavStack.new()
nav.screen_changed.connect(_on_screen_changed)
add_child(nav)
on_install()
func _internal_app_changed(app_path: String, mode: int) -> void:
if manifest == null:
return
if app_path != manifest.app_path:
if visible:
visible = false
on_close()
app_closed.emit()
return
match mode:
HudGroups.Mode.FULLSCREEN, HudGroups.Mode.INSERT:
if not visible:
visible = true
if not manifest.preserves_state:
nav.reset_to_default()
elif nav.is_empty():
nav.push_default()
on_open(mode)
app_opened.emit(mode)
HudGroups.Mode.GAMEPLAY:
if visible:
visible = false
on_close()
app_closed.emit()
# --- Lifecycle hooks — subclasses override ---
func on_install() -> void:
pass
func on_open(_mode: int) -> void:
pass
func on_close() -> void:
pass
func on_insert_deactivated() -> void:
# Default: close only if active in INSERT mode. FULLSCREEN apps override to customize.
if manifest and HudGroups.is_app_active(manifest.app_path):
if HudGroups.get_active_mode() == HudGroups.Mode.INSERT:
HudGroups.close_app()
func _on_screen_changed(_screen_id: String) -> void:
pass
func handle_intent(_action: String, _params: Dictionary) -> void:
pass