-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce ViewRouter Component (#337)
* improved handling of lsp failure state * add static mock to lsp connection test case * Integrate Event Broker in LspStatusManager * Add ViewRouter POC * Fix code formatting bug * Add method to retrieve observables * Add listeners for combined state streams and view update request * Add listeners for combined state streams and view update request * Add listeners for combined state streams and view update request * Add functionality for hot event streams that track latest event (#340) * Add functionality for hot subscribers that track latest event * Add test to ensure event stream isolation * Fix missing subscription disposal in test * Use autoConnect to implicitly manage stream connection * Remove active view update request listener * Add ViewRouter tests * Remove public constructor * Remove public constructor and unused event in tests * Add comments * Add documentation for EventBroker * Remove ViewRouter initialization * Remove LspInitializingView from ID enum * Add documentation for ViewRouter * Refactor and enhance EventBroker tests * Refactor ViewRouter tests for clarity * Remove PluginState class into separate file * Add documentation to subscription management logic * Add support for notifying multiple late-subscribers over time of latest state (#342) * Remove CODE_REFERENCE_VIEW * Rename newActiveViewId to newActiveView * Rename ViewId class to AmazonQViewType * Revert "Integrate Event Broker in LspStatusManager" This reverts commit 374e549. * Revert "improved handling of lsp failure state" This reverts commit 13c55ac. * Refactor EventBroker and enhance tests (#343) --------- Co-authored-by: Nicolas Borges <[email protected]>
- Loading branch information
Showing
8 changed files
with
473 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
plugin/src/software/aws/toolkits/eclipse/amazonq/views/router/AmazonQViewType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package software.aws.toolkits.eclipse.amazonq.views.router; | ||
|
||
public enum AmazonQViewType { | ||
TOOLKIT_LOGIN_VIEW, CHAT_VIEW, DEPENDENCY_MISSING_VIEW, RE_AUTHENTICATE_VIEW, CHAT_ASSET_MISSING_VIEW, | ||
LSP_STARTUP_FAILED_VIEW | ||
} |
10 changes: 10 additions & 0 deletions
10
plugin/src/software/aws/toolkits/eclipse/amazonq/views/router/PluginState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package software.aws.toolkits.eclipse.amazonq.views.router; | ||
|
||
import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.AuthState; | ||
import software.aws.toolkits.eclipse.amazonq.lsp.manager.LspState; | ||
|
||
public record PluginState(AuthState authState, LspState lspState) { | ||
} |
156 changes: 156 additions & 0 deletions
156
plugin/src/software/aws/toolkits/eclipse/amazonq/views/router/ViewRouter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package software.aws.toolkits.eclipse.amazonq.views.router; | ||
|
||
import io.reactivex.rxjava3.core.Observable; | ||
import io.reactivex.rxjava3.schedulers.Schedulers; | ||
import software.aws.toolkits.eclipse.amazonq.broker.api.EventObserver; | ||
import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.AuthState; | ||
import software.aws.toolkits.eclipse.amazonq.lsp.manager.LspState; | ||
import software.aws.toolkits.eclipse.amazonq.plugin.Activator; | ||
|
||
/** | ||
* Routes to appropriate views based on the combined auth and lsp states (plugin | ||
* state). This router observes plugin state changes and updates the active view | ||
* accordingly, broadcasting view changes through the event broker. | ||
*/ | ||
public final class ViewRouter implements EventObserver<PluginState> { | ||
|
||
private AmazonQViewType activeView; | ||
|
||
/** | ||
* Constructs a ViewRouter with the specified builder configuration. Initializes | ||
* state observation and sets up view routing logic. Primarily useful for | ||
* testing and injecting observables. When none are passed, the router get the | ||
* observables directly from the event broker and combines them to create the | ||
* PluginState stream. | ||
* | ||
* @param builder The builder containing auth and lsp state observables | ||
*/ | ||
private ViewRouter(final Builder builder) { | ||
if (builder.authStateObservable == null) { | ||
builder.authStateObservable = Activator.getEventBroker().ofObservable(AuthState.class); | ||
} | ||
|
||
if (builder.lspStateObservable == null) { | ||
builder.lspStateObservable = Activator.getEventBroker().ofObservable(LspState.class); | ||
} | ||
|
||
/* | ||
* Combine auth and lsp streams and publish combined state updates on changes to | ||
* either stream consisting of the latest events from both streams (this will | ||
* happen only after one event has been published to both streams): | ||
*/ | ||
Observable.combineLatest(builder.authStateObservable, builder.lspStateObservable, PluginState::new) | ||
.observeOn(Schedulers.computation()).subscribe(this::onEvent); | ||
} | ||
|
||
public static Builder builder() { | ||
return new Builder(); | ||
} | ||
|
||
/** | ||
* Handles plugin state changes by refreshing the active view. | ||
* | ||
* @param pluginState The current combined state auth and lsp state of the plugin | ||
*/ | ||
@Override | ||
public void onEvent(final PluginState pluginState) { | ||
refreshActiveView(pluginState); | ||
} | ||
|
||
/** | ||
* Determines and sets the appropriate view based on the order of resolution. | ||
* View selection follows a priority order: | ||
* 1. Dependency Missing: can browsers be created. | ||
* 2. LSP Startup Failed: has the language server initialization failed (not pending/active). | ||
* 3. Chat UI Asset Missing: have chat assets been fetched and available? | ||
* 4. Authentication Logged out: if user logged out, needs to login again. | ||
* 5. Authentication Expired: if auth has expired, needs to be refreshed. | ||
* 5. Chat View: happy path. | ||
* | ||
* @param pluginState The current combined auth and lsp state of the plugin | ||
*/ | ||
private void refreshActiveView(final PluginState pluginState) { | ||
AmazonQViewType newActiveView; | ||
|
||
if (isDependencyMissing()) { // TODO: dependency missing check logic needs to be implemented | ||
newActiveView = AmazonQViewType.DEPENDENCY_MISSING_VIEW; | ||
} else if (pluginState.lspState() == LspState.FAILED) { | ||
newActiveView = AmazonQViewType.LSP_STARTUP_FAILED_VIEW; | ||
} else if (isChatUIAssetMissing()) { // TODO: chat missing logic needs to be implemented | ||
newActiveView = AmazonQViewType.CHAT_ASSET_MISSING_VIEW; | ||
} else if (pluginState.authState().isLoggedOut()) { | ||
newActiveView = AmazonQViewType.TOOLKIT_LOGIN_VIEW; | ||
} else if (pluginState.authState().isExpired()) { | ||
newActiveView = AmazonQViewType.RE_AUTHENTICATE_VIEW; | ||
} else { | ||
newActiveView = AmazonQViewType.CHAT_VIEW; | ||
} | ||
|
||
updateActiveView(newActiveView); | ||
} | ||
|
||
/** | ||
* Updates the active view if it has changed and notifies observers of the | ||
* change. | ||
* | ||
* @param newActiveViewId The new view to be activated | ||
*/ | ||
private void updateActiveView(final AmazonQViewType newActiveViewId) { | ||
if (activeView != newActiveViewId) { | ||
activeView = newActiveViewId; | ||
notifyActiveViewChange(); | ||
} | ||
} | ||
|
||
/** | ||
* Broadcasts the active view change through the event broker. | ||
*/ | ||
private void notifyActiveViewChange() { | ||
Activator.getEventBroker().post(AmazonQViewType.class, activeView); | ||
} | ||
|
||
/** | ||
* Checks if browsers available are compatible or is dependency missing. | ||
* TODO: Implement actual dependency checking logic | ||
* | ||
* @return true if dependencies are missing, false otherwise | ||
*/ | ||
private boolean isDependencyMissing() { | ||
return false; | ||
} | ||
|
||
/** | ||
* Checks if required chat UI assets are missing. | ||
* TODO: Implement actual asset checking logic | ||
* | ||
* @return true if chat UI assets are missing, false otherwise | ||
*/ | ||
private boolean isChatUIAssetMissing() { | ||
return false; | ||
} | ||
|
||
public static final class Builder { | ||
|
||
private Observable<AuthState> authStateObservable; | ||
private Observable<LspState> lspStateObservable; | ||
|
||
public Builder withAuthStateObservable(final Observable<AuthState> authStateObservable) { | ||
this.authStateObservable = authStateObservable; | ||
return this; | ||
} | ||
|
||
public Builder withLspStateObservable(final Observable<LspState> lspStateObservable) { | ||
this.lspStateObservable = lspStateObservable; | ||
return this; | ||
} | ||
|
||
public ViewRouter build() { | ||
return new ViewRouter(this); | ||
} | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.