From 28344988e8fe87de57ddec937fab2b2ddd038acc Mon Sep 17 00:00:00 2001 From: Ishan Taldekar Date: Mon, 10 Feb 2025 15:03:51 -0500 Subject: [PATCH] Integrate browser based views in ViewContainer --- plugin/plugin.xml | 19 ---- .../AbstractQChatEditorActionsHandler.java | 2 +- .../amazonq/lsp/LspStartupActivity.java | 35 ++---- .../eclipse/amazonq/plugin/Activator.java | 5 +- .../browser/AmazonQBrowserProvider.java | 5 + .../amazonq/views/AmazonQChatWebview.java | 47 ++------ .../eclipse/amazonq/views/AmazonQView.java | 73 ++++++++----- .../amazonq/views/AmazonQViewContainer.java | 101 ++++++++---------- .../amazonq/views/ReauthenticateView.java | 25 +---- .../amazonq/views/ToolkitLoginWebview.java | 31 ++---- .../amazonq/views/ViewVisibilityManager.java | 21 ++-- .../views/actions/AmazonQCommonActions.java | 25 +++-- .../CustomizationDialogContributionItem.java | 8 +- .../FeedbackDialogContributionItem.java | 14 +-- .../amazonq/views/actions/SignoutAction.java | 8 +- .../ToggleAutoTriggerContributionItem.java | 7 +- 16 files changed, 160 insertions(+), 266 deletions(-) diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 980fdc93..1932c2a9 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -41,13 +41,6 @@ category="amazonq" inject="true"> - - - - - - - diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQChatEditorActionsHandler.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQChatEditorActionsHandler.java index af363a4f..563dbe6e 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQChatEditorActionsHandler.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQChatEditorActionsHandler.java @@ -97,7 +97,7 @@ private void sendGenericCommand(final String selection, final String genericComm private void openQChat() { Display.getDefault().syncExec(() -> { - ViewVisibilityManager.showChatView("shortcut"); + ViewVisibilityManager.showDefaultView("shortcut"); }); } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/LspStartupActivity.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/LspStartupActivity.java index 5995f715..3174594c 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/LspStartupActivity.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/LspStartupActivity.java @@ -9,28 +9,24 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.lsp4e.LanguageServersRegistry; +import org.eclipse.lsp4e.LanguageServiceAccessor; +import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup; +import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IStartup; import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; -import software.aws.toolkits.eclipse.amazonq.util.Constants; +import software.aws.toolkits.eclipse.amazonq.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.util.AutoTriggerDocumentListener; import software.aws.toolkits.eclipse.amazonq.util.AutoTriggerPartListener; import software.aws.toolkits.eclipse.amazonq.util.AutoTriggerTopLevelListener; -import software.aws.toolkits.eclipse.amazonq.plugin.Activator; -import software.aws.toolkits.eclipse.amazonq.telemetry.ToolkitTelemetryProvider; -import software.aws.toolkits.eclipse.amazonq.telemetry.metadata.ExceptionMetadata; -import software.aws.toolkits.eclipse.amazonq.views.ViewConstants; +import software.aws.toolkits.eclipse.amazonq.util.Constants; import software.aws.toolkits.eclipse.amazonq.util.ToolkitNotification; import software.aws.toolkits.eclipse.amazonq.util.UpdateUtils; -import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup; +import software.aws.toolkits.eclipse.amazonq.views.ViewConstants; +import software.aws.toolkits.eclipse.amazonq.views.ViewVisibilityManager; import software.aws.toolkits.eclipse.amazonq.views.actions.ToggleAutoTriggerContributionItem; -import org.eclipse.lsp4e.LanguageServiceAccessor; -import org.eclipse.swt.widgets.Display; -import org.eclipse.lsp4e.LanguageServersRegistry; @SuppressWarnings("restriction") public class LspStartupActivity implements IStartup { @@ -76,20 +72,9 @@ private void launchWebview() { String viewId = "software.aws.toolkits.eclipse.amazonq.views.ToolkitLoginWebview"; IWorkbench workbench = PlatformUI.getWorkbench(); workbench.getDisplay().asyncExec(new Runnable() { + @Override public void run() { - try { - showTelemetryNotification(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - if (window != null) { - IWorkbenchPage page = window.getActivePage(); - page.showView(viewId); - ToolkitTelemetryProvider.emitOpenModuleEventMetric(viewId, "firstStartUp", "none"); - Activator.getPluginStore().put(ViewConstants.PREFERENCE_STORE_PLUGIN_FIRST_STARTUP_KEY, "true"); - } - } catch (PartInitException e) { - Activator.getLogger().warn("Error occurred during auto loading of plugin", e); - ToolkitTelemetryProvider.emitOpenModuleEventMetric(viewId, "firstStartUp", ExceptionMetadata.scrubException("Plugin load error", e)); - } + ViewVisibilityManager.showDefaultView("launch"); } }); } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/plugin/Activator.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/plugin/Activator.java index c6baa8b0..bbb4f627 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/plugin/Activator.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/plugin/Activator.java @@ -16,10 +16,11 @@ import software.aws.toolkits.eclipse.amazonq.providers.lsp.LspProviderImpl; import software.aws.toolkits.eclipse.amazonq.telemetry.service.DefaultTelemetryService; import software.aws.toolkits.eclipse.amazonq.telemetry.service.TelemetryService; -import software.aws.toolkits.eclipse.amazonq.util.PluginLogger; import software.aws.toolkits.eclipse.amazonq.util.CodeReferenceLoggingService; import software.aws.toolkits.eclipse.amazonq.util.DefaultCodeReferenceLoggingService; import software.aws.toolkits.eclipse.amazonq.util.LoggingService; +import software.aws.toolkits.eclipse.amazonq.util.PluginLogger; +import software.aws.toolkits.eclipse.amazonq.views.router.ViewRouter; public class Activator extends AbstractUIPlugin { @@ -33,6 +34,8 @@ public class Activator extends AbstractUIPlugin { private static PluginStore pluginStore; private static EventBroker eventBroker = new EventBroker(); + private static ViewRouter viewRouter = ViewRouter.builder().build(); + public Activator() { super(); plugin = this; diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/providers/browser/AmazonQBrowserProvider.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/providers/browser/AmazonQBrowserProvider.java index 1189b8cf..bbd09c9c 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/providers/browser/AmazonQBrowserProvider.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/providers/browser/AmazonQBrowserProvider.java @@ -5,6 +5,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; @@ -63,6 +64,10 @@ public final int getBrowserStyle() { */ public final boolean setupBrowser(final Composite parent) { var browser = new Browser(parent, getBrowserStyle()); + + GridData layoutData = new GridData(GridData.FILL_BOTH); + browser.setLayoutData(layoutData); + checkWebViewCompatibility(browser.getBrowserType()); // only set the browser if compatible webview browser can be found for the // platform diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQChatWebview.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQChatWebview.java index 8540557e..200098e2 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQChatWebview.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQChatWebview.java @@ -15,8 +15,6 @@ import software.aws.toolkits.eclipse.amazonq.chat.ChatCommunicationManager; import software.aws.toolkits.eclipse.amazonq.chat.ChatStateManager; import software.aws.toolkits.eclipse.amazonq.chat.ChatTheme; -import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.AuthState; -import software.aws.toolkits.eclipse.amazonq.lsp.manager.LspStatusManager; import software.aws.toolkits.eclipse.amazonq.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.providers.assets.ChatWebViewAssetProvider; import software.aws.toolkits.eclipse.amazonq.providers.assets.WebViewAssetProvider; @@ -45,10 +43,11 @@ public AmazonQChatWebview() { this.actionHandler = new AmazonQChatViewActionHandler(chatCommunicationManager); this.webViewAssetProvider = new ChatWebViewAssetProvider(); this.chatTheme = new ChatTheme(); + this.webViewAssetProvider = new ChatWebViewAssetProvider(); } @Override - public final void createPartControl(final Composite parent) { + public final Composite setupView(final Composite parent) { setupParentBackground(parent); browser = chatStateManager.getBrowser(parent); // attempt to use existing browser with chat history if present, else create a @@ -59,10 +58,9 @@ public final void createPartControl(final Composite parent) { // if setup of amazon q view fails due to missing webview dependency, switch to // that view and don't setup rest of the content if (!result) { - canDisposeState = true; - showDependencyMissingView("update"); - return; + return parent; } + browser = getAndUpdateStateManager(); browser.setVisible(false); @@ -76,12 +74,12 @@ public void completed(final ProgressEvent event) { }); } }); + } else { updateBrowser(browser); } - AuthState authState = Activator.getLoginService().getAuthState(); - setupAmazonQView(parent, authState); + super.setupView(parent); parent.addDisposeListener(e -> chatStateManager.preserveBrowser()); amazonQCommonActions = getAmazonQCommonActions(); @@ -112,8 +110,9 @@ public void completed(final ProgressEvent event) { } }); - // Check if user is authenticated and build view accordingly - onEvent(authState); + Optional content = webViewAssetProvider.getContent(); + browser.setText(content.get()); + return parent; } private Browser getAndUpdateStateManager() { @@ -122,34 +121,6 @@ private Browser getAndUpdateStateManager() { return browser; } - @Override - public final void onEvent(final AuthState authState) { - Display.getDefault().asyncExec(() -> { - amazonQCommonActions.updateActionVisibility(authState, getViewSite()); - if (authState.isExpired()) { - canDisposeState = true; - ViewVisibilityManager.showReAuthView("update"); - } else if (authState.isLoggedOut()) { - canDisposeState = true; - ViewVisibilityManager.showLoginView("update"); - } else { - // if browser is not null and there is no chat prior state, start a new blank - // chat view - if (browser != null && !browser.isDisposed() && !chatStateManager.hasPreservedState()) { - Optional content = webViewAssetProvider.getContent(); - if (!content.isPresent() && !LspStatusManager.getInstance().lspFailed()) { - canDisposeState = true; - if (!LspStatusManager.getInstance().lspFailed()) { - ViewVisibilityManager.showChatAssetMissingView("update"); - } - } else { - browser.setText(content.get()); // Display the chat client - } - } - } - }); - } - private void handleMessageFromUI(final Browser browser, final Object[] arguments) { try { commandParser.parseCommand(arguments) diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQView.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQView.java index 94665062..95a0405a 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQView.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQView.java @@ -7,23 +7,27 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.IViewSite; import io.reactivex.rxjava3.disposables.Disposable; -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.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.providers.browser.AmazonQBrowserProvider; import software.aws.toolkits.eclipse.amazonq.util.ThemeDetector; import software.aws.toolkits.eclipse.amazonq.views.actions.AmazonQCommonActions; -public abstract class AmazonQView extends ViewPart implements EventObserver { +public abstract class AmazonQView extends BaseAmazonQView { private AmazonQBrowserProvider browserProvider; private AmazonQCommonActions amazonQCommonActions; private static final ThemeDetector THEME_DETECTOR = new ThemeDetector(); - private Disposable authStateSubscription; + private Disposable signOutActionAuthStateSubscription; + private Disposable feedbackDialogAuthStateSubscription; + private Disposable customizationDialogAuthStateSubscription; + private Disposable toggleAutoTriggerAuthStateSubscription; + + private IViewSite viewSite; protected AmazonQView() { this.browserProvider = new AmazonQBrowserProvider(); @@ -52,11 +56,18 @@ protected final void updateBrowser(final Browser browser) { browserProvider.updateBrowser(browser); } - protected final void setupAmazonQView(final Composite parent, final AuthState authState) { - setupBrowserBackground(parent); - setupActions(authState); - setupAuthStatusListeners(); - disableBrowserContextMenu(); + @Override + public Composite setupView(final Composite parent) { + Browser browser = getBrowser(); + + if (browser != null && !browser.isDisposed()) { + setupBrowserBackground(parent); + setupActions(); + setupAuthStatusListeners(); + disableBrowserContextMenu(); + } + + return parent; } protected final void disableBrowserContextMenu() { @@ -68,28 +79,25 @@ private void setupBrowserBackground(final Composite parent) { getBrowser().setBackground(bgColor); } - protected final void showDependencyMissingView(final String source) { - Display.getCurrent().asyncExec(() -> { - try { - ViewVisibilityManager.showDependencyMissingView(source); - } catch (Exception e) { - Activator.getLogger().error("Error occured while attempting to show missing webview dependencies view", e); - } - }); + private void setupActions() { + amazonQCommonActions = new AmazonQCommonActions(viewSite); } - private void setupActions(final AuthState authState) { - amazonQCommonActions = new AmazonQCommonActions(authState, getViewSite()); + private void setupAuthStatusListeners() { + signOutActionAuthStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, + amazonQCommonActions.getSignoutAction()); + feedbackDialogAuthStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, + amazonQCommonActions.getFeedbackDialogContributionAction()); + customizationDialogAuthStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, + amazonQCommonActions.getCustomizationDialogContributionAction()); + toggleAutoTriggerAuthStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, + amazonQCommonActions.getToggleAutoTriggerContributionAction()); } - private void setupAuthStatusListeners() { - authStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, this); - Activator.getEventBroker().subscribe(AuthState.class, amazonQCommonActions.getSignoutAction()); - Activator.getEventBroker().subscribe(AuthState.class, amazonQCommonActions.getFeedbackDialogContributionAction()); - Activator.getEventBroker().subscribe(AuthState.class, amazonQCommonActions.getCustomizationDialogContributionAction()); + public void setViewSite(final IViewSite viewSite) { + this.viewSite = viewSite; } - @Override public final void setFocus() { if (!browserProvider.hasWebViewDependency()) { return; @@ -105,8 +113,19 @@ public final void setFocus() { */ @Override public void dispose() { - authStateSubscription.dispose(); - super.dispose(); + if (signOutActionAuthStateSubscription != null && !signOutActionAuthStateSubscription.isDisposed()) { + signOutActionAuthStateSubscription.dispose(); + } + if (feedbackDialogAuthStateSubscription != null && !feedbackDialogAuthStateSubscription.isDisposed()) { + feedbackDialogAuthStateSubscription.dispose(); + } + if (customizationDialogAuthStateSubscription != null + && !customizationDialogAuthStateSubscription.isDisposed()) { + customizationDialogAuthStateSubscription.dispose(); + } + if (toggleAutoTriggerAuthStateSubscription != null && !toggleAutoTriggerAuthStateSubscription.isDisposed()) { + toggleAutoTriggerAuthStateSubscription.dispose(); + } } } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQViewContainer.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQViewContainer.java index cbd8e0d6..655c9ab3 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQViewContainer.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/AmazonQViewContainer.java @@ -10,9 +10,11 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.part.ViewPart; +import io.reactivex.rxjava3.disposables.Disposable; import software.aws.toolkits.eclipse.amazonq.broker.api.EventObserver; import software.aws.toolkits.eclipse.amazonq.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.views.actions.AmazonQStaticActions; @@ -23,79 +25,59 @@ public final class AmazonQViewContainer extends ViewPart implements EventObserve private Composite parentComposite; private StackLayout layout; private Map views; - private AmazonQViewType activeId; - private BaseAmazonQView activeView; + private AmazonQViewType activeViewType; + private BaseAmazonQView currentView; + private Disposable activeViewTypeSubscription; public AmazonQViewContainer() { - Activator.getEventBroker().subscribe(AmazonQViewType.class, this); - } - - /* Router should be initialized, then init view container - * ViewRouter.Initialize() - * viewcontainer.init(activeViewId) - */ - - /* - * When container is disposed and being reopened, class will be recreated - * need to call showView to reset viewContainer && follow up with init call to container - * 1. showView(viewContainer.ID) - * 2. viewContainer.init(currentView) - */ - - public void initializeViews(final AmazonQViewType currentActiveViewId) { - - //init map containing all views - var dependencyMissingView = new DependencyMissingView(); - var chatAssetMissingView = new ChatAssetMissingView(); - var reAuthView = new ReauthenticateView(); - var lspFailedView = new LspStartUpFailedView(); views = Map.of( - AmazonQViewType.CHAT_ASSET_MISSING_VIEW, chatAssetMissingView, - AmazonQViewType.DEPENDENCY_MISSING_VIEW, dependencyMissingView, - AmazonQViewType.RE_AUTHENTICATE_VIEW, reAuthView, - AmazonQViewType.LSP_STARTUP_FAILED_VIEW, lspFailedView - ); - - //default view passed in from router - //possible we'll use chatView as default? - activeId = currentActiveViewId; + AmazonQViewType.CHAT_ASSET_MISSING_VIEW, new DependencyMissingView(), + AmazonQViewType.DEPENDENCY_MISSING_VIEW, new ChatAssetMissingView(), + AmazonQViewType.RE_AUTHENTICATE_VIEW, new ReauthenticateView(), + AmazonQViewType.LSP_STARTUP_FAILED_VIEW, new LspStartUpFailedView(), + AmazonQViewType.CHAT_VIEW, new AmazonQChatWebview(), + AmazonQViewType.TOOLKIT_LOGIN_VIEW, new ToolkitLoginWebview() + ); } + @Override public void createPartControl(final Composite parent) { - parentComposite = parent; layout = new StackLayout(); parent.setLayout(layout); - //add base stylings GridLayout gridLayout = new GridLayout(1, false); - gridLayout.marginLeft = 20; - gridLayout.marginRight = 20; - gridLayout.marginTop = 10; - gridLayout.marginBottom = 10; + gridLayout.marginHeight = gridLayout.marginWidth = 0; parent.setLayout(gridLayout); + parentComposite = parent; + setupStaticMenuActions(); - updateChildView(); + if (activeViewTypeSubscription == null || activeViewTypeSubscription.isDisposed()) { + activeViewTypeSubscription = Activator.getEventBroker().subscribe(AmazonQViewType.class, this); + } } - /* change methodology for setupMenuActions -- move outside of viewContainer? - * will need ability to switch between the two based on which view is displaying && authState - * if viewId = static view --> new AmazonQStaticActions(getViewSite()); - * if viewId = common view --> new AmazonQCommonActions(AuthState, getViewSite()); - */ private void setupStaticMenuActions() { new AmazonQStaticActions(getViewSite()); } private void updateChildView() { Display.getDefault().asyncExec(() -> { - BaseAmazonQView newView = views.get(activeId); - - if (activeView != null) { - activeView.dispose(); - if (layout.topControl != null) { - layout.topControl.dispose(); + BaseAmazonQView newView = views.get(activeViewType); + + if (currentView != null) { + Control[] children = parentComposite.getChildren(); + for (Control child : children) { + if (child != null && !child.isDisposed()) { + child.dispose(); + } } + + currentView.dispose(); + } + + if (activeViewType == AmazonQViewType.CHAT_VIEW || activeViewType == AmazonQViewType.TOOLKIT_LOGIN_VIEW) { + ((AmazonQView) newView).setViewSite(getViewSite()); } Composite newViewComposite = newView.setupView(parentComposite); @@ -105,17 +87,17 @@ private void updateChildView() { layout.topControl = newViewComposite; parentComposite.layout(true, true); - activeView = newView; + currentView = newView; }); } @Override - public void onEvent(final AmazonQViewType newViewId) { - if (newViewId.equals(activeId) || !views.containsKey(newViewId)) { + public void onEvent(final AmazonQViewType newViewType) { + if (newViewType.equals(activeViewType) || !views.containsKey(newViewType)) { return; } - activeId = newViewId; + activeViewType = newViewType; if (!parentComposite.isDisposed()) { updateChildView(); } @@ -129,9 +111,14 @@ public void setFocus() { @Override public void dispose() { - if (activeView != null) { - activeView.dispose(); + if (currentView != null) { + currentView.dispose(); } + + if (activeViewTypeSubscription != null && !activeViewTypeSubscription.isDisposed()) { + activeViewTypeSubscription.dispose(); + } + super.dispose(); } } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ReauthenticateView.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ReauthenticateView.java index 0c4ab96f..a5854a7c 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ReauthenticateView.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ReauthenticateView.java @@ -14,12 +14,8 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Link; -import io.reactivex.rxjava3.disposables.Disposable; -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.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.telemetry.UiTelemetryProvider; import software.aws.toolkits.eclipse.amazonq.util.Constants; @@ -28,7 +24,7 @@ import software.aws.toolkits.eclipse.amazonq.views.actions.SignoutAction; -public final class ReauthenticateView extends CallToActionView implements EventObserver { +public final class ReauthenticateView extends CallToActionView { public static final String ID = "software.aws.toolkits.eclipse.amazonq.views.ReauthenticateView"; private static final String ICON_PATH = "icons/AmazonQ64.png"; @@ -37,12 +33,7 @@ public final class ReauthenticateView extends CallToActionView implements EventO private static final String BUTTON_LABEL = "Re-authenticate"; private static final String LINK_LABEL = "Sign out"; - private Disposable authStateSubscription; - public ReauthenticateView() { - // It is necessary for this view to be an `AuthStatusChangedListener` to switch the view back to Q Chat after the authentication - // flow is successful. Without this listener, the re-authentication will succeed but the view will remain present. - authStateSubscription = Activator.getEventBroker().subscribe(AuthState.class, this); } @Override @@ -97,14 +88,6 @@ public void widgetSelected(final SelectionEvent e) { } }); } - @Override - public void onEvent(final AuthState authState) { - Display.getDefault().asyncExec(() -> { - if (authState.isLoggedIn()) { - ViewVisibilityManager.showChatView("update"); - } - }); - } @Override protected void updateButtonStyle(final Button button) { @@ -136,12 +119,6 @@ protected void updateButtonStyle(final Button button) { }); } - @Override - public void dispose() { - authStateSubscription.dispose(); - } - - private void resizeButtonFont(final Button button, final int newFontSize) { Font currentFont = button.getFont(); FontData[] fontData = currentFont.getFontData(); diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ToolkitLoginWebview.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ToolkitLoginWebview.java index 64971a0e..a9d40a1e 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ToolkitLoginWebview.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ToolkitLoginWebview.java @@ -9,8 +9,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; -import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.AuthState; -import software.aws.toolkits.eclipse.amazonq.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.providers.assets.ToolkitLoginWebViewAssetProvider; import software.aws.toolkits.eclipse.amazonq.providers.assets.WebViewAssetProvider; import software.aws.toolkits.eclipse.amazonq.telemetry.UiTelemetryProvider; @@ -36,15 +34,16 @@ public ToolkitLoginWebview() { } @Override - public void createPartControl(final Composite parent) { + public Composite setupView(final Composite parent) { + super.setupView(parent); + setupParentBackground(parent); var result = setupBrowser(parent); // if setup of amazon q view fails due to missing webview dependency, switch to // that view // and don't setup rest of the content if (!result) { - showDependencyMissingView("update"); - return; + return parent; } var browser = getBrowser(); @@ -61,9 +60,6 @@ public void completed(final ProgressEvent event) { } }); - AuthState authState = Activator.getLoginService().getAuthState(); - setupAmazonQView(parent, authState); - new BrowserFunction(browser, ViewConstants.COMMAND_FUNCTION_NAME) { @Override public Object function(final Object[] arguments) { @@ -82,24 +78,9 @@ public Object function(final Object[] arguments) { }; amazonQCommonActions = getAmazonQCommonActions(); + browser.setText(webViewAssetProvider.getContent().get()); - // Check if user is authenticated and build view accordingly - onEvent(authState); - } - - @Override - public void onEvent(final AuthState authState) { - var browser = getBrowser(); - Display.getDefault().asyncExec(() -> { - amazonQCommonActions.updateActionVisibility(authState, getViewSite()); - if (!authState.isLoggedIn()) { - if (!browser.isDisposed()) { - browser.setText(webViewAssetProvider.getContent().get()); - } - } else { - ViewVisibilityManager.showChatView("update"); - } - }); + return parent; } @Override diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ViewVisibilityManager.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ViewVisibilityManager.java index 3e4d799d..bd2f4d33 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ViewVisibilityManager.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/ViewVisibilityManager.java @@ -41,18 +41,11 @@ private ViewVisibilityManager() { ); public static void showDefaultView(final String source) { - var authState = Activator.getLoginService().getAuthState(); - if (authState.isExpired()) { - showReAuthView(source); - } else if (authState.isLoggedIn()) { - showChatView(source); - } else { - showLoginView(source); - } + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showLoginView(final String source) { - showMutuallyExclusiveView(TOOLKIT_LOGIN_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showViewContainer(final String source) { @@ -61,23 +54,23 @@ public static void showViewContainer(final String source) { } public static void showChatView(final String source) { - showMutuallyExclusiveView(CHAT_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showDependencyMissingView(final String source) { - showMutuallyExclusiveView(DEPENDENCY_MISSING_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showReAuthView(final String source) { - showMutuallyExclusiveView(RE_AUTHENTICATE_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showChatAssetMissingView(final String source) { - showMutuallyExclusiveView(CHAT_ASSET_MISSING_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showLspStartUpFailedView(final String source) { - showMutuallyExclusiveView(LSP_STARTUP_FAILED_VIEW, source); + showMutuallyExclusiveView(AMAZON_Q_VIEW_CONTAINER, source); } public static void showCodeReferenceView(final String source) { diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/AmazonQCommonActions.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/AmazonQCommonActions.java index 66b32954..f27ab6f3 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/AmazonQCommonActions.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/AmazonQCommonActions.java @@ -9,8 +9,6 @@ import org.eclipse.ui.IActionBars; import org.eclipse.ui.IViewSite; -import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.AuthState; - public final class AmazonQCommonActions { @@ -24,10 +22,11 @@ public final class AmazonQCommonActions { private ViewLogsAction viewLogsAction; private ReportAnIssueAction reportAnIssueAction; - public AmazonQCommonActions(final AuthState authState, final IViewSite viewSite) { + private IActionBars bars; + + public AmazonQCommonActions(final IViewSite viewSite) { createActions(viewSite); contributeToActionBars(viewSite); - updateActionVisibility(authState, viewSite); } public SignoutAction getSignoutAction() { @@ -60,8 +59,15 @@ private void createActions(final IViewSite viewSite) { private void contributeToActionBars(final IViewSite viewSite) { IActionBars bars = viewSite.getActionBars(); - fillLocalPullDown(bars.getMenuManager()); - fillLocalToolBar(bars.getToolBarManager()); + IMenuManager menuManager = bars.getMenuManager(); + IToolBarManager toolBarManager = bars.getToolBarManager(); + + menuManager.removeAll(); + toolBarManager.removeAll(); + bars.updateActionBars(); + + fillLocalPullDown(menuManager); + fillLocalToolBar(toolBarManager); } private void fillLocalPullDown(final IMenuManager manager) { @@ -90,11 +96,4 @@ private void fillLocalToolBar(final IToolBarManager manager) { // No actions added to the view toolbar at this time } - public void updateActionVisibility(final AuthState authState, final IViewSite viewSite) { - signoutAction.updateVisibility(authState); - feedbackDialogContributionItem.updateVisibility(authState); - customizationDialogContributionItem.updateVisibility(authState); - toggleAutoTriggerContributionItem.updateVisibility(authState); - } - } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/CustomizationDialogContributionItem.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/CustomizationDialogContributionItem.java index 5e8e3cfa..df27294d 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/CustomizationDialogContributionItem.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/CustomizationDialogContributionItem.java @@ -38,7 +38,8 @@ public CustomizationDialogContributionItem(final IViewSite viewSite) { } // TODO: Need to update this method as the login condition has to be Pro login using IAM identity center - public void updateVisibility(final AuthState authState) { + @Override + public void onEvent(final AuthState authState) { this.setVisible(authState.isLoggedIn() && authState.loginType().equals(LoginType.IAM_IDENTITY_CENTER)); Display.getDefault().asyncExec(() -> { viewSite.getActionBars().getMenuManager().markDirty(); @@ -46,11 +47,6 @@ public void updateVisibility(final AuthState authState) { }); } - @Override - public void onEvent(final AuthState authState) { - updateVisibility(authState); - } - @Override public void fill(final Menu menu, final int index) { MenuItem menuItem = new MenuItem(menu, SWT.NONE, index); diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/FeedbackDialogContributionItem.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/FeedbackDialogContributionItem.java index 172e3733..4f95a9e2 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/FeedbackDialogContributionItem.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/FeedbackDialogContributionItem.java @@ -27,20 +27,16 @@ public FeedbackDialogContributionItem(final IViewSite viewSite) { ); } - public void updateVisibility(final AuthState authState) { - feedbackDialogContributionItem.setVisible(authState.isLoggedIn()); - Display.getDefault().asyncExec(() -> { - viewSite.getActionBars().getMenuManager().markDirty(); - viewSite.getActionBars().getMenuManager().update(true); - }); - } - public DialogContributionItem getDialogContributionItem() { return feedbackDialogContributionItem; } @Override public void onEvent(final AuthState authState) { - updateVisibility(authState); + feedbackDialogContributionItem.setVisible(authState.isLoggedIn()); + Display.getDefault().asyncExec(() -> { + viewSite.getActionBars().getMenuManager().markDirty(); + viewSite.getActionBars().getMenuManager().update(true); + }); } } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/SignoutAction.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/SignoutAction.java index 4eeae8ea..a2ee5455 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/SignoutAction.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/SignoutAction.java @@ -12,6 +12,7 @@ import software.aws.toolkits.eclipse.amazonq.util.ThreadingUtils; public final class SignoutAction extends Action implements EventObserver { + public SignoutAction() { setText("Sign out"); } @@ -37,12 +38,9 @@ public void run() { }); } - public void updateVisibility(final AuthState authState) { - this.setEnabled(authState.isLoggedIn()); - } - @Override public void onEvent(final AuthState authState) { - updateVisibility(authState); + this.setEnabled(authState.isLoggedIn()); } + } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/ToggleAutoTriggerContributionItem.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/ToggleAutoTriggerContributionItem.java index 6ba13676..825daf91 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/ToggleAutoTriggerContributionItem.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/views/actions/ToggleAutoTriggerContributionItem.java @@ -12,11 +12,12 @@ import org.eclipse.swt.widgets.MenuItem; import org.eclipse.ui.IViewSite; +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.plugin.Activator; import software.aws.toolkits.eclipse.amazonq.telemetry.UiTelemetryProvider; -public final class ToggleAutoTriggerContributionItem extends ContributionItem { +public final class ToggleAutoTriggerContributionItem extends ContributionItem implements EventObserver { public static final String AUTO_TRIGGER_ENABLEMENT_KEY = "aws.q.autotrigger.eclipse"; private static final String PAUSE_TEXT = "Pause Auto-Suggestions"; @@ -34,9 +35,11 @@ public ToggleAutoTriggerContributionItem(final IViewSite viewSite) { var resumeImageDescriptor = Activator.imageDescriptorFromPlugin("org.eclipse.ui.cheatsheets", "icons/elcl16/start_task.png"); resume = resumeImageDescriptor.createImage(Display.getCurrent()); + Activator.getEventBroker().subscribe(AuthState.class, this); } - public void updateVisibility(final AuthState authState) { + @Override + public void onEvent(final AuthState authState) { this.setVisible(authState.isLoggedIn()); Display.getDefault().asyncExec(() -> { viewSite.getActionBars().getMenuManager().markDirty();