Skip to content

Commit

Permalink
Update webview theme on editor theme change (#85)
Browse files Browse the repository at this point in the history
CLOSE
https://linear.app/sourcegraph/issue/CODY-3622/webview-theme-should-update-on-theme-changed


https://github.com/user-attachments/assets/4b388c44-456d-4a91-8a79-a594e51a56f9

Test Plan:

Try following the steps shown in the demo video above to switch theme
and confirm the webview is updated accordingly.

---------

Co-authored-by: Piotr Karczmarz <[email protected]>
  • Loading branch information
abeatrix and PiotrKarczmarz authored Sep 5, 2024
1 parent 890b8e7 commit 8c274b0
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### Added

- The chat view style now updates to match the theme of the editor on theme change. [pull/85](https://github.com/sourcegraph/cody-vs/pull/85)

### Changed

### Deprecated
Expand Down
9 changes: 8 additions & 1 deletion src/Cody.Core/Infrastructure/IColorThemeService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -8,6 +8,8 @@ namespace Cody.Core.Infrastructure
{
public interface IThemeService
{
event EventHandler<IColorThemeChangedEvent> ThemeChanged;

bool IsDarkTheme();

IReadOnlyDictionary<string, string> GetColors();
Expand All @@ -32,3 +34,8 @@ public FontInformation(string fontName, float size)
public float Size { get; protected set; }
}
}

public class IColorThemeChangedEvent : EventArgs
{
public string ThemingScript { get; set; }
}
4 changes: 3 additions & 1 deletion src/Cody.UI/Controls/WebView2Dev.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ private async void InitWebView2(object sender, RoutedEventArgs e)
await InitializeWebView();
}

public static WebviewController InitializeController(string themeScript)
public static WebviewController InitializeController(string themeScript, ILog logger)
{
_controller.SetLogger(logger);
_controller.SetThemeScript(themeScript);

return _controller;
}

Expand Down
41 changes: 34 additions & 7 deletions src/Cody.UI/Controls/WebviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Cody.Core.Logging;

namespace Cody.UI.Controls
{
Expand All @@ -16,6 +17,8 @@ public class WebviewController

private ICommand _sendMessageCommand;

private ILog _logger;

public WebviewController()
{
}
Expand Down Expand Up @@ -135,10 +138,27 @@ private async Task ApplyThemingScript()
public void SetThemeScript(string colorThemeScript)
{
_colorThemeScript = colorThemeScript;
// We might want to apply the theme immediately if the webview is already loaded.
// if (_webview.CoreWebView2.IsDocumentOpen) {
// _ = ApplyThemingScript();
// }
}

public async void OnThemeChanged(object sender, IColorThemeChangedEvent e)
{
try
{
string updatedScript = e.ThemingScript;
if (updatedScript != _colorThemeScript)
{
_logger.Debug("Applying VS theme change to WebView ...");

SetThemeScript(updatedScript);
await ApplyThemingScript();

_logger.Debug("Theme change applied.");
}
}
catch (Exception ex)
{
_logger.Error("Applying theme change to WebView failed.", ex);
}
}

public void SetHtml(string html)
Expand Down Expand Up @@ -189,9 +209,16 @@ public void SetHtml(string html)
";

private static string GetThemeScript(string colorTheme) => $@"
document.documentElement.dataset.ide = 'VisualStudio';
{colorTheme}
(function() {{
document.documentElement.dataset.ide = 'VisualStudio';
document.documentElement.style = '';
{colorTheme}
}})();
";

public void SetLogger(ILog logger)
{
_logger = logger;
}
}
}
5 changes: 3 additions & 2 deletions src/Cody.VisualStudio/CodyPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,16 @@ private void InitializeServices()

StatusbarService = new StatusbarService();
InitializeService = new InitializeCallback(UserSettingsService, VersionService, VsVersionService, StatusbarService, SolutionService, Logger);
ThemeService = new ThemeService(this);
ThemeService = new ThemeService(this, Logger);
FileService = new FileService(this, Logger);
var statusCenterService = this.GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>();
ProgressService = new ProgressService(statusCenterService);
NotificationHandlers = new NotificationHandlers(UserSettingsService, AgentNotificationsLogger, FileService);
NotificationHandlers.OnOptionsPageShowRequest += HandleOnOptionsPageShowRequest;
ProgressNotificationHandlers = new ProgressNotificationHandlers(ProgressService);

WebView2Dev.InitializeController(ThemeService.GetThemingScript());
var sidebarController = WebView2Dev.InitializeController(ThemeService.GetThemingScript(), Logger);
ThemeService.ThemeChanged += sidebarController.OnThemeChanged;
NotificationHandlers.PostWebMessageAsJson = WebView2Dev.PostWebMessageAsJson;

var runningDocumentTable = this.GetService<SVsRunningDocumentTable, IVsRunningDocumentTable>();
Expand Down
36 changes: 28 additions & 8 deletions src/Cody.VisualStudio/Services/ThemeService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Cody.Core.Infrastructure;
using Cody.Core.Infrastructure;
using Microsoft.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Settings;
using Microsoft.VisualStudio.Shell;
Expand All @@ -10,19 +10,39 @@
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Cody.Core.Logging;

namespace Cody.VisualStudio.Services
{
public class ThemeService : IThemeService
{
private IServiceProvider serviceProvider;
private readonly IServiceProvider _serviceProvider;
private readonly ILog _logger;

public ThemeService(IServiceProvider serviceProvider)
public event EventHandler<IColorThemeChangedEvent> ThemeChanged;

public ThemeService(IServiceProvider serviceProvider, ILog logger)
{
this.serviceProvider = serviceProvider;
_serviceProvider = serviceProvider;
_logger = logger;

VSColorTheme.ThemeChanged += HandleThemeChanges;
}

// TODO: Update the webviews when the theme changes.
// VSColorTheme.ThemeChanged += VSColorTheme_ThemeChanged;

private async void HandleThemeChanges(ThemeChangedEventArgs e)
{
try
{
await Task.Delay(1000); // Short delay to allow VS to update colors
var latest = GetThemingScript();
ThemeChanged?.Invoke(this, new IColorThemeChangedEvent { ThemingScript = latest });
}
catch (Exception ex)
{
_logger.Error("Processing VS Theme change failed.", ex);
}
}

public IReadOnlyDictionary<string, string> GetColors()
Expand Down Expand Up @@ -51,7 +71,7 @@ public FontInformation GetUIFont()

private FontInformation GetFontInfo(Guid categoryGuid)
{
var storage = (IVsFontAndColorStorage)serviceProvider.GetService(typeof(SVsFontAndColorStorage));
var storage = (IVsFontAndColorStorage)_serviceProvider.GetService(typeof(SVsFontAndColorStorage));
storage.OpenCategory(categoryGuid, (uint)(__FCSTORAGEFLAGS.FCSF_LOADDEFAULTS | __FCSTORAGEFLAGS.FCSF_READONLY));

var logFont = new LOGFONTW[1];
Expand All @@ -70,7 +90,7 @@ public bool IsDarkTheme()
const string darkTheme = "{1ded0138-47ce-435e-84ef-9ec1f439b749}";
const string systemTheme = "{619dac1e-8220-4bd9-96fb-75ceb61a6107}";

var settingsManager = new ShellSettingsManager(serviceProvider);
var settingsManager = new ShellSettingsManager(_serviceProvider);
var store = settingsManager.GetReadOnlySettingsStore(SettingsScope.UserSettings);
var themeId = store.GetString("Theme", "BackupThemeId");

Expand Down

0 comments on commit 8c274b0

Please sign in to comment.