Skip to content

Decouple TimeControl and TimeUI via event bus - #217

Open
sandesh-sp wants to merge 8 commits into
feat/tile-url-consolidationfrom
feat/timecontrol-event-decoupling
Open

Decouple TimeControl and TimeUI via event bus#217
sandesh-sp wants to merge 8 commits into
feat/tile-url-consolidationfrom
feat/timecontrol-event-decoupling

Conversation

@sandesh-sp

@sandesh-sp sandesh-sp commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Decouples TimeControl (time state + layer reloading) from TimeUI (the legacy bottom time slider) so they communicate over the mmgisAPI event bus instead of direct method calls.

  • Removes TimeControl's direct import TimeUI and the TimeControl.timeUI reference; migrates all former TimeControl.timeUI consumers (QueryURL, AnimationTool, DrawTool_Templater, UserInterfaceDefault_) to use TimeUI directly, guarded on the widget being mounted
  • Moves TimeUI instantiation out of TimeControl.init() into essence.js, gated on !mobile && !modernMode && time.enabled (usesLegacyTimeUI())
  • Introduces events: time:changeRequested (widgets → TimeControl), time:change (TimeControl → widgets), time:layersReloaded
  • TimeControl owns and derives all time state: seeds it in init() (no reload — layers aren't on the map yet), performs the single initial reload in fina(); TimeUI mirrors committed state and recognizes echoes of its own requests (_lastEmitted, consumed on match; _suppressChangeEmit) so nothing reloads twice
  • Extracts parseTimeWithOffset / parseTimeToSeconds into a shared timeUtils.js with unit tests
  • Validates dates in TimeControl.setTime (returns false on invalid input instead of throwing mid-mutation)
  • Implements TimeControl.toggleTimeUImmgisAPI.toggleTimeUI has always referenced it but it never existed; it now delegates to the Coordinates-owned #toggleTimeUI button

Files changed

  • src/essence/Basics/TimeControl_/TimeControl.js
  • src/essence/Basics/TimeControl_/TimeUI.js
  • src/essence/Basics/TimeControl_/timeUtils.js (new)
  • src/essence/essence.js
  • src/essence/Ancillary/QueryURL.js
  • src/essence/Tools/Animation/AnimationTool.js
  • src/essence/Tools/Draw/DrawTool_Templater.js
  • src/essence/Basics/UserInterface_/UserInterfaceDefault_.js
  • tests/unit/timeUtils.spec.js (new)

Test plan

  • Time-enabled layers reload correctly on user time change (no double reload)
  • Bottom time slider (TimeUI) renders and drives time changes when time.enabled and not mobile/modern mode
  • mmgisAPI time events (time:change, time:layersReloaded) fire as expected
  • Share/deeplink URL generation works on a time-enabled mission (includes startTime/endTime/live)
  • Animation tool: step/interval stay in sync with the TimeUI controls
  • Draw templater "set time start/end" buttons set the time and fit the timeline window
  • Layers tool "set global time from extent" reloads layers once
  • mmgisAPI.setTime with invalid dates returns false without breaking state

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sqp49fHnucNf9uvAT6QfYn

Replace the direct TimeControl <-> TimeUI calls with mmgisAPI events
(time:userChanged, time:setRequested, time:layersReloaded, time:change)
and move shared time parsing into timeUtils. TimeUI now renders only in
the classic layout; modern layout uses the Timeline tool.
sandesh-sp and others added 5 commits July 27, 2026 10:44
… management

- Decouple time control events from UI updates to prevent redundant resyncs
- Enhance time initialization logic to derive start/end times from committed state
- Update time utility functions to handle null/undefined inputs gracefully
- Introduce unit tests for time parsing utilities
The event-bus decoupling removed TimeControl.timeUI but left consumers
referencing it: QueryURL threw on every share-URL generation for
time-enabled missions, the Draw templater's set-time buttons threw on
click, and AnimationTool's TimeUI integration and
UserInterfaceDefault_'s popover realignment silently no-op'd behind
guards. Point them all at TimeUI directly, guarded on the widget
actually being mounted (TimeUI.startTempus) where they touch its DOM.

Also:
- Clear TimeUI._lastEmitted once its echo is consumed so a later
  external commit of identical times isn't mistaken for an echo and
  skipped
- Validate dates in TimeControl.setTime and return false instead of
  throwing RangeError mid-mutation on invalid input
- Implement TimeControl.toggleTimeUI (mmgisAPI.toggleTimeUI has always
  referenced it, but it never existed) by delegating to the
  Coordinates-owned '#toggleTimeUI' button
- Replace 'Invalid Date' string-coercion checks with isNaN(getTime())
- Deduplicate the legacy-TimeUI layout condition in essence.js into
  usesLegacyTimeUI()

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sqp49fHnucNf9uvAT6QfYn
_initialStart: null,
_initialEnd: null,
// Payload of the last emitted time:changeRequested — used to recognize
// the committed echo on time:change and skip a redundant resync

@CarsonDavis CarsonDavis Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time:change -> time:changeCompleted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants