From 681dfae2cb5f413dac40fa36f98dd359252609f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Kukie=C5=82ka?= Date: Fri, 22 Dec 2023 15:31:11 +0100 Subject: [PATCH] Fix issues with chat colours after switching UI theme (#230) It fixes [#229](https://github.com/sourcegraph/jetbrains/issues/229) ## Test plan 1. Ask Cody Chat question to which it will reply with various layout elements (list, code snippets, etc) 2. Change theme in settings or using `Themes` action. 3. Verify that chat text is readable, as well as that there is clear colour distinction between user and assistant sections. Both sections colors should also correspond to the chosen theme. Repeat the above starting from different themes. ## PR notes We should try to avoid hardcoding color computations and instead always try to inherit them from the parent elements. This way recompilations after theme change etc. are straightforward. If we have to hardcode anything we must make sure it's in a place where it will be recomputed on either theme change or a repaint. ![Colors fix](https://github.com/sourcegraph/jetbrains/assets/1519649/10fcc661-d1e6-4c48-82ca-8cd8f133be43) ![Colors fix](https://github.com/sourcegraph/jetbrains/assets/1519649/480b3e26-5a40-49e0-8826-d4706aa8c170) ![Colors fix](https://github.com/sourcegraph/jetbrains/assets/1519649/7457b489-2d8f-4d23-a4ec-b8ea56655415) --- TESTING.md | 83 ++++++++++++------- .../AssistantMessageWithSettingsButton.java | 28 ------- .../com/sourcegraph/cody/chat/MessagePanel.kt | 2 +- .../com/sourcegraph/cody/chat/MessagePart.kt | 3 +- .../cody/chat/PanelWithGradientBorder.kt | 20 +++-- .../com/sourcegraph/cody/ui/HtmlViewer.kt | 17 ---- 6 files changed, 66 insertions(+), 87 deletions(-) delete mode 100644 src/main/java/com/sourcegraph/cody/chat/AssistantMessageWithSettingsButton.java diff --git a/TESTING.md b/TESTING.md index 0e466f54f4..617369fdc7 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1,32 +1,33 @@ ## Checklist - Onboarding - - [ ] [Sign in with GitHub](#sign-in-with-github) - - [ ] [Sign in with GitLab](#sign-in-with-gitlab) - - [ ] [Sign in with Google](#sign-in-with-google) + - [ ] [Sign in with GitHub](#sign-in-with-github) + - [ ] [Sign in with GitLab](#sign-in-with-gitlab) + - [ ] [Sign in with Google](#sign-in-with-google) - Autocomplete - - [ ] [Single-line autocomplete](#single-line-autocomplete) - - [ ] [Multi-line autocomplete](#multi-line-autocomplete) - - [ ] [Infilling autocomplete](#infilling-autocomplete) - - [ ] [Cycle through autocomplete](#cycle-through-autocomplete) + - [ ] [Single-line autocomplete](#single-line-autocomplete) + - [ ] [Multi-line autocomplete](#multi-line-autocomplete) + - [ ] [Infilling autocomplete](#infilling-autocomplete) + - [ ] [Cycle through autocomplete](#cycle-through-autocomplete) - Commands - - [ ] [General commands availability](#general-commands-availability) - - [ ] [Explain Selected Code (Detailed)](#explain-selected-code-detailed) - - [ ] [Explain Selected Code (High Level)](#explain-selected-code-high-level) - - [ ] [Generate Docstring](#generate-docstring) - - [ ] [Generate Unit Test](#generate-unit-test) - - [ ] [Improve Variable Names](#improve-variable-names) - - [ ] [Smell Code](#smell-code) + - [ ] [General commands availability](#general-commands-availability) + - [ ] [Explain Selected Code (Detailed)](#explain-selected-code-detailed) + - [ ] [Explain Selected Code (High Level)](#explain-selected-code-high-level) + - [ ] [Generate Docstring](#generate-docstring) + - [ ] [Generate Unit Test](#generate-unit-test) + - [ ] [Improve Variable Names](#improve-variable-names) + - [ ] [Smell Code](#smell-code) - Chat - - [ ] [Autoscroll to latest message](#autoscroll-to-latest-message) - - [ ] [Read chat history without interruptions](#read-chat-history-without-interruptions) + - [ ] [Autoscroll to latest message](#autoscroll-to-latest-message) + - [ ] [Read chat history without interruptions](#read-chat-history-without-interruptions) - Product-led growth - - [ ] [Cody Free/Pro subscription tab](#cody-freepro-subscription-tab) - - [ ] [Cody Free/Pro rate limit errors](#cody-freepro-rate-limit-errors) + - [ ] [Cody Free/Pro subscription tab](#cody-freepro-subscription-tab) + - [ ] [Cody Free/Pro rate limit errors](#cody-freepro-rate-limit-errors) - Other - - [ ] [Search Selection on Sourcegraph Web](#search-selection-on-sourcegraph-web) - - [ ] [Automatic repository recognition](#automatic-repository-recognition) - - [ ] [Persistent custom repository](#persistent-custom-repository) + - [ ] [Search Selection on Sourcegraph Web](#search-selection-on-sourcegraph-web) + - [ ] [Automatic repository recognition](#automatic-repository-recognition) + - [ ] [Persistent custom repository](#persistent-custom-repository) + - [ ] [Colour scheme changes](#colour-scheme-changes) ## Onboarding @@ -45,11 +46,13 @@ Prerequisite: You have to **sign out** from all existing accounts. ### Sign in with GitLab -Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-github), and the authorization is also done through the browser. Expected behaviour is identical. +Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-github), and the authorization is also done +through the browser. Expected behaviour is identical. ### Sign in with Google -Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-github), and the authorization is also done through the browser. Expected behaviour is identical. +Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-github), and the authorization is also done +through the browser. Expected behaviour is identical. ## Autocomplete @@ -128,7 +131,8 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour * User is automatically switched to `Chat` tab. -* Chat responds with a **detailed** description of the selected code and will elaborate on the fields, classes, and methods, going into technical details, often structuring the text in bullet points. +* Chat responds with a **detailed** description of the selected code and will elaborate on the fields, classes, and + methods, going into technical details, often structuring the text in bullet points. ### Explain Selected Code (High Level) @@ -156,7 +160,8 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour * User is automatically switched to `Chat` tab. -* Language has been identified as Java, so the documentation syntax is also in that language (see: `@param` and `@return` tags). +* Language has been identified as Java, so the documentation syntax is also in that language (see: `@param` + and `@return` tags). * Chat responds with generated docstring, similar to this: ```java /* @@ -218,7 +223,8 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour * User is automatically switched to `Chat` tab. -* Chat responds with **potential issues** and **suggestions** like missing nullability checks or input sanitization (response may vary). +* Chat responds with **potential issues** and **suggestions** like missing nullability checks or input sanitization ( + response may vary). ## Chat @@ -240,7 +246,8 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour -* Scrollbar is **not moving automatically** while new message tokens are generated. You can easily read older messages without interruptions and scrolling is smooth. +* Scrollbar is **not moving automatically** while new message tokens are generated. You can easily read older messages + without interruptions and scrolling is smooth. ## [Product-led growth](https://handbook.sourcegraph.com/departments/data-analytics/product-led-growth/) @@ -283,17 +290,20 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour -* Browser automatically opened at `sourcegraph.com` with the `Code Search` feature. Results are found with `System.out.println` occurrences. +* Browser automatically opened at `sourcegraph.com` with the `Code Search` feature. Results are found + with `System.out.println` occurrences. ### Automatic repository recognition 1. Open project with enabled Git VCS. This repository must be publicly available on GitHub. 2. Open to `Cody` toolbar. -3. Click on repository button to open `Context Selection` dialog. Button is placed inside `Cody` toolbar on left, bottom corner. +3. Click on repository button to open `Context Selection` dialog. Button is placed inside `Cody` toolbar on left, bottom + corner. #### Expected behaviour -* Repository `Git URL` has been successfully inferred from VCS history. Value is similar to `github.com/sourcegraph/jetbrains`. +* Repository `Git URL` has been successfully inferred from VCS history. Value is similar + to `github.com/sourcegraph/jetbrains`. ### Persistent custom repository @@ -307,3 +317,16 @@ Onboarding through GitLab is similar to [Sign in with GitHub](#sign-in-with-gith #### Expected behaviour * Repository `Git URL` is same as before restart. + +### Colour scheme changes + +1. Ask Cody Chat question to which it will reply with various layout elements (list, code snippets, etc) +2. Change theme in settings or using Themes action. +3. Verify that chat text is readable, as well as that there is clear colour distinction between user and assistant + sections. Both sections colors should also correspond to the chosen theme. + +Repeat the above starting from different themes. + +#### Expected behaviour + +Changing theme should lead to full repaint of the colours according to the current theme. \ No newline at end of file diff --git a/src/main/java/com/sourcegraph/cody/chat/AssistantMessageWithSettingsButton.java b/src/main/java/com/sourcegraph/cody/chat/AssistantMessageWithSettingsButton.java deleted file mode 100644 index 2fc8c0897e..0000000000 --- a/src/main/java/com/sourcegraph/cody/chat/AssistantMessageWithSettingsButton.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sourcegraph.cody.chat; - -import static com.sourcegraph.cody.chat.ChatUIConstants.TEXT_MARGIN; - -import com.intellij.ui.BrowserHyperlinkListener; -import com.intellij.util.ui.JBInsets; -import com.intellij.util.ui.SwingHelper; -import com.intellij.util.ui.UIUtil; -import com.sourcegraph.cody.agent.protocol.Speaker; -import com.sourcegraph.config.GoToPluginSettingsButtonFactory; -import java.awt.*; -import javax.swing.*; -import org.jetbrains.annotations.NotNull; - -public class AssistantMessageWithSettingsButton extends PanelWithGradientBorder { - public AssistantMessageWithSettingsButton(@NotNull String htmlTextContent) { - super(ChatUIConstants.ASSISTANT_MESSAGE_GRADIENT_WIDTH, Speaker.ASSISTANT); - this.setLayout(new BorderLayout()); - JEditorPane jEditorPane = SwingHelper.createHtmlViewer(true, null, null, null); - jEditorPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE); - jEditorPane.setFocusable(true); - jEditorPane.setMargin( - JBInsets.create(new Insets(TEXT_MARGIN, TEXT_MARGIN, TEXT_MARGIN, TEXT_MARGIN))); - SwingHelper.setHtml(jEditorPane, htmlTextContent, UIUtil.getActiveTextColor()); - this.add(jEditorPane, BorderLayout.CENTER); - this.add(GoToPluginSettingsButtonFactory.createGoToPluginSettingsButton(), BorderLayout.EAST); - } -} diff --git a/src/main/kotlin/com/sourcegraph/cody/chat/MessagePanel.kt b/src/main/kotlin/com/sourcegraph/cody/chat/MessagePanel.kt index 58a494ad67..56876da09c 100644 --- a/src/main/kotlin/com/sourcegraph/cody/chat/MessagePanel.kt +++ b/src/main/kotlin/com/sourcegraph/cody/chat/MessagePanel.kt @@ -68,7 +68,7 @@ class MessagePanel( private fun addAsNewTextComponent(renderedHtml: String) { val textPane: JEditorPane = createHtmlViewer(getInlineCodeBackgroundColor(chatMessage.speaker)) - SwingHelper.setHtml(textPane, renderedHtml, UIUtil.getLabelForeground()) + SwingHelper.setHtml(textPane, renderedHtml, null) val textEditorComponent = TextPart(textPane) this.lastMessagePart = textEditorComponent add(textEditorComponent.component) diff --git a/src/main/kotlin/com/sourcegraph/cody/chat/MessagePart.kt b/src/main/kotlin/com/sourcegraph/cody/chat/MessagePart.kt index 5a48ccf79a..e85cb61678 100644 --- a/src/main/kotlin/com/sourcegraph/cody/chat/MessagePart.kt +++ b/src/main/kotlin/com/sourcegraph/cody/chat/MessagePart.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable import com.intellij.util.ui.SwingHelper -import com.intellij.util.ui.UIUtil import javax.swing.JComponent import javax.swing.JEditorPane @@ -19,7 +18,7 @@ sealed interface MessagePart class TextPart(val component: JEditorPane) : MessagePart { fun updateText(text: String) { - SwingHelper.setHtml(component, text, UIUtil.getLabelForeground()) + SwingHelper.setHtml(component, text, null) } } diff --git a/src/main/kotlin/com/sourcegraph/cody/chat/PanelWithGradientBorder.kt b/src/main/kotlin/com/sourcegraph/cody/chat/PanelWithGradientBorder.kt index a59be1600b..f635628712 100644 --- a/src/main/kotlin/com/sourcegraph/cody/chat/PanelWithGradientBorder.kt +++ b/src/main/kotlin/com/sourcegraph/cody/chat/PanelWithGradientBorder.kt @@ -2,6 +2,7 @@ package com.sourcegraph.cody.chat import com.intellij.openapi.ui.VerticalFlowLayout import com.intellij.ui.ColorUtil +import com.intellij.util.ui.JBUI import com.intellij.util.ui.UIUtil import com.sourcegraph.cody.agent.protocol.Speaker import com.sourcegraph.cody.ui.Colors @@ -14,23 +15,24 @@ import javax.swing.border.Border open class PanelWithGradientBorder(private val gradientWidth: Int, speaker: Speaker) : JPanel() { - private val isHuman: Boolean + private val isHuman: Boolean = speaker == Speaker.HUMAN - init { - val emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0) - val background = UIUtil.getPanelBackground() - val topBorder: Border = - BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.brighter(background, 2)) + private fun recomputeLayout() { + val panelBackground = UIUtil.getPanelBackground() + val separatorForeground = JBUI.CurrentTheme.CustomFrameDecorations.separatorForeground() + val topBorder: Border = BorderFactory.createMatteBorder(1, 0, 0, 0, separatorForeground) val bottomBorder: Border = - BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.brighter(background, 3)) + BorderFactory.createMatteBorder(0, 0, 1, 0, ColorUtil.brighter(separatorForeground, 1)) val topAndBottomBorder: Border = BorderFactory.createCompoundBorder(topBorder, bottomBorder) - isHuman = speaker == Speaker.HUMAN + val emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0) + this.border = if (isHuman) emptyBorder else topAndBottomBorder - this.background = if (isHuman) ColorUtil.darker(background, 2) else background this.layout = VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false) + this.background = if (isHuman) ColorUtil.darker(panelBackground, 2) else panelBackground } override fun paintComponent(g: Graphics) { + recomputeLayout() super.paintComponent(g) paintLeftBorderGradient(g) } diff --git a/src/main/kotlin/com/sourcegraph/cody/ui/HtmlViewer.kt b/src/main/kotlin/com/sourcegraph/cody/ui/HtmlViewer.kt index 532c69a17d..15a741558e 100644 --- a/src/main/kotlin/com/sourcegraph/cody/ui/HtmlViewer.kt +++ b/src/main/kotlin/com/sourcegraph/cody/ui/HtmlViewer.kt @@ -1,8 +1,6 @@ package com.sourcegraph.cody.ui -import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.ui.BrowserHyperlinkListener -import com.intellij.ui.ColorUtil import com.intellij.util.ui.HTMLEditorKitBuilder import com.intellij.util.ui.JBInsets import com.intellij.util.ui.SwingHelper @@ -10,17 +8,12 @@ import com.sourcegraph.cody.chat.ChatUIConstants import java.awt.Color import java.awt.Insets import javax.swing.JEditorPane -import javax.swing.text.html.HTMLEditorKit object HtmlViewer { @JvmStatic fun createHtmlViewer(backgroundColor: Color): JEditorPane { val jEditorPane = SwingHelper.createHtmlViewer(true, null, null, null) jEditorPane.editorKit = HTMLEditorKitBuilder().withWordWrapViewFactory().build() - val htmlEditorKit = jEditorPane.editorKit as HTMLEditorKit - val fontFamilyAndSize = createFontFamilyAndSizeCssRule() - val backgroundColorCss = createBackgroundColorCssRule(backgroundColor) - htmlEditorKit.styleSheet.addRule("code { $backgroundColorCss$fontFamilyAndSize}") jEditorPane.isFocusable = true jEditorPane.margin = JBInsets.create( @@ -32,14 +25,4 @@ object HtmlViewer { jEditorPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE) return jEditorPane } - - private fun createBackgroundColorCssRule(backgroundColor: Color) = - "background-color: #" + ColorUtil.toHex(backgroundColor) + ";" - - private fun createFontFamilyAndSizeCssRule(): String { - val schemeForCurrentUITheme = EditorColorsManager.getInstance().schemeForCurrentUITheme - val editorFontName = schemeForCurrentUITheme.editorFontName - val editorFontSize = schemeForCurrentUITheme.editorFontSize - return "font-family:'" + editorFontName + "'; font-size:" + editorFontSize + "pt;" - } }