Skip to content

Commit

Permalink
Integrate browser based views in ViewContainer
Browse files Browse the repository at this point in the history
  • Loading branch information
taldekar committed Feb 10, 2025
1 parent c2a9446 commit 2834498
Show file tree
Hide file tree
Showing 16 changed files with 160 additions and 266 deletions.
19 changes: 0 additions & 19 deletions plugin/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,6 @@
category="amazonq"
inject="true">
</view>
<view
id="software.aws.toolkits.eclipse.amazonq.views.AmazonQChatWebview"
name="Amazon Q"
icon="icons/AmazonQ.png"
class="software.aws.toolkits.eclipse.amazonq.views.AmazonQChatWebview"
inject="true">
</view>
<view
class="software.aws.toolkits.eclipse.amazonq.views.AmazonQCodeReferenceView"
icon="icons/AmazonQ.png"
Expand All @@ -69,11 +62,6 @@
</activity>
<activity id="software.aws.toolkits.eclipse.amazonq.activity.ChatAssetMissingView" name="Amazon Q Chat Missing">
</activity>
<activityPatternBinding
activityId="software.aws.toolkits.eclipse.amazonq.activity.AmazonQChatWebview"
isEqualityPattern="true"
pattern="amazon-q-eclipse/software.aws.toolkits.eclipse.amazonq.views.AmazonQChatWebview">
</activityPatternBinding>
<activityPatternBinding
activityId="software.aws.toolkits.eclipse.amazonq.activity.AmazonQCodeReferenceView"
isEqualityPattern="true"
Expand Down Expand Up @@ -112,12 +100,6 @@
relationship="stack"
visible="false">
</view>
<view
id="software.aws.toolkits.eclipse.amazonq.views.AmazonQChatWebview"
relative="software.aws.toolkits.eclipse.amazonq.views.AmazonQViewContainer"
relationship="stack"
visible="false">
</view>
<view
id="software.aws.toolkits.eclipse.amazonq.views.AmazonQCodeReferenceView"
relative="software.aws.toolkits.eclipse.amazonq.views.AmazonQViewContainer"
Expand Down Expand Up @@ -381,7 +363,6 @@
<equals value="org.eclipse.ui.DefaultTextEditor"/>
<equals value="org.eclipse.jdt.ui.CompilationUnitEditor"/>
<equals value="org.eclipse.ui.genericeditor.GenericEditor"/>
<equals value="software.aws.toolkits.eclipse.amazonq.views.AmazonQChatWebview" />
</or>
</with>
</and>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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");
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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();
Expand Down Expand Up @@ -112,8 +110,9 @@ public void completed(final ProgressEvent event) {
}
});

// Check if user is authenticated and build view accordingly
onEvent(authState);
Optional<String> content = webViewAssetProvider.getContent();
browser.setText(content.get());
return parent;
}

private Browser getAndUpdateStateManager() {
Expand All @@ -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<String> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<AuthState> {
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();
Expand Down Expand Up @@ -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() {
Expand All @@ -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;
Expand All @@ -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();
}
}

}
Loading

0 comments on commit 2834498

Please sign in to comment.