Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update webview theme on editor theme change #85

Merged
merged 5 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional try/catch because we're handling event.

{
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)
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller can use logger now :)

_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
{
Copy link
Collaborator

@PiotrKarczmarz PiotrKarczmarz Sep 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added try/catch here :) In general every code that is handling event should be in the try/catch.

Also Task.Delay(100).Wait() was blocking UI thread, so changed the method signature to allow awaiting it.

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
Loading