Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

Latest commit

 

History

History
59 lines (48 loc) · 3.29 KB

File metadata and controls

59 lines (48 loc) · 3.29 KB

The UIController class creates views and associated viewmodels for each UI we have, and controls the UI logic graph. It uses various state machines to define the UI logic graph.

State machines

The UI logic graph is controlled by various state machines defined in ConfigureLogicStates and ConfigureUIHandlingStates

ConfigureLogicStates

ConfigureLogicStates defines the one state machine per UI group: - Authentication - Repository Clone - Repository Creation - Repository Publish, - Pull Requests (List, Detail, Creation)

All state machines have a common state of None (nothing happened yet), End (we're done, cleanup) and Finish (final state once cleanup is done), and UI-specific states that relate to what views the UI needs to show (Login, TwoFactor, PullRequestList, etc). States are defined in the enum UIViewType

All state machines support a variety of triggers for going from one state to another. These triggers are defined in the enum Trigger. Cancel and Finish are supported by all states (any state machine regardless of its current state supports exiting via Cancel (ends with success flag set to false) and Finish (ends with success flag set to true). Since most UI flows we support are linear (login followed by 2fa followed by clone followed by ending the flow), most states support the Next trigger to continue, and when at the end of a ui flow, Next ends it with success.

The Pull Requests UI flow is non-linear (there are more than one transition from the list view - it can go to the detail view, or the pr creation view, or other views), it does not support the Next trigger and instead has its own triggers.

ConfigureUIHandlingStates

ConfigureUIHandlingStates defines a state machine uiStateMachine connected to the transition observable, and executes whatever logic is needed to load the requested state, usually by creating the view and viewmodel that the UI state requires. Whenever a state transition happens in uiStateMachine, if the state requires loading a view, this view is sent back to the rendering code via the transition observable. When the state machine reaches the End state, the completion observable is completed with a flag indicating whether the ui flow ended successfully or was cancelled (via the Next/Finish triggers or the Cancel trigger) .

The transitions between states are dynamically evaluated at runtime based on the logic defined in ConfigureLogicStates. When uiStateMachine receives a trigger request, it passes that trigger to the state machine corresponding to the ui flow that's currently running (Authentication, Clone, etc), and that state machine determines which state to go to next.

In theory, uiStateMachine has no knowledge of the logic graph, and the only thing it's responsible for is loading UI whenever a state is entered, and cleaning up objects when things are done - making it essentially a big switch with nice entry and exit conditions. In practice, we need to configure the valid triggers from one state to the other just so we can call the corresponding state machine that handles the logic (defined in ConfigureLogicStates). There is a bit of code duplication because of this, and there's some room for improvement here, but because we have a small number of triggers, it's not a huge deal.