Skip to content

Commit 672e3b8

Browse files
Merge pull request #402 from konstantingross/feature/Additional_NativeTheme_implementations
Remaining implementation of the NativeTheme API
2 parents 05de407 + b7960eb commit 672e3b8

File tree

5 files changed

+241
-8
lines changed

5 files changed

+241
-8
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.ComponentModel;
2+
3+
namespace ElectronNET.API.Entities
4+
{
5+
/// <summary>
6+
/// Defines the ThemeSourceMode enumeration.
7+
/// </summary>
8+
public enum ThemeSourceMode
9+
{
10+
/// <summary>
11+
/// Operating system default.
12+
/// </summary>
13+
[Description("system")]
14+
System,
15+
16+
/// <summary>
17+
/// Light theme.
18+
/// </summary>
19+
[Description("light")]
20+
Light,
21+
22+
/// <summary>
23+
/// Dark theme.
24+
/// </summary>
25+
[Description("dark")]
26+
Dark
27+
}
28+
}

ElectronNET.API/NativeTheme.cs

Lines changed: 163 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using System.Threading.Tasks;
1+
using System;
2+
using System.Threading.Tasks;
3+
using ElectronNET.API.Entities;
4+
using ElectronNET.API.Extensions;
25

36
namespace ElectronNET.API
47
{
@@ -32,11 +35,95 @@ internal static NativeTheme Instance
3235
}
3336

3437
/// <summary>
35-
/// A `Boolean` for if the OS / Chromium currently has a dark mode enabled or is
36-
/// being instructed to show a dark-style UI.If you want to modify this value you
37-
/// should use `themeSource` below.
38+
/// Setting this property to <see cref="ThemeSourceMode.System"/> will remove the override and everything will be reset to the OS default. By default 'ThemeSource' is <see cref="ThemeSourceMode.System"/>.
39+
/// <para/>
40+
/// Settings this property to <see cref="ThemeSourceMode.Dark"/> will have the following effects:
41+
/// <list type="bullet">
42+
/// <item>
43+
/// <description><see cref="ShouldUseDarkColorsAsync"/> will be <see langword="true"/> when accessed</description>
44+
/// </item>
45+
/// <item>
46+
/// <description>Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the dark UI.</description>
47+
/// </item>
48+
/// <item>
49+
/// <description>Any UI the OS renders on macOS including menus, window frames, etc. will use the dark UI.</description>
50+
/// </item>
51+
/// <item>
52+
/// <description>The 'prefers-color-scheme' CSS query will match 'dark' mode.</description>
53+
/// </item>
54+
/// <item>
55+
/// <description>The 'updated' event will be emitted</description>
56+
/// </item>
57+
/// </list>
58+
/// <para/>
59+
/// Settings this property to <see cref="ThemeSourceMode.Light"/> will have the following effects:
60+
/// <list type="bullet">
61+
/// <item>
62+
/// <description><see cref="ShouldUseDarkColorsAsync"/> will be <see langword="false"/> when accessed</description>
63+
/// </item>
64+
/// <item>
65+
/// <description>Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the light UI.</description>
66+
/// </item>
67+
/// <item>
68+
/// <description>Any UI the OS renders on macOS including menus, window frames, etc. will use the light UI.</description>
69+
/// </item>
70+
/// <item>
71+
/// <description>The 'prefers-color-scheme' CSS query will match 'light' mode.</description>
72+
/// </item>
73+
/// <item>
74+
/// <description>The 'updated' event will be emitted</description>
75+
/// </item>
76+
/// </list>
77+
/// The usage of this property should align with a classic "dark mode" state machine in your application where the user has three options.
78+
/// <para/>
79+
/// <list type="bullet">
80+
/// <item>
81+
/// <description>Follow OS: SetThemeSource(ThemeSourceMode.System);</description>
82+
/// </item>
83+
/// <item>
84+
/// <description>Dark Mode: SetThemeSource(ThemeSourceMode.Dark);</description>
85+
/// </item>
86+
/// <item>
87+
/// <description>Light Mode: SetThemeSource(ThemeSourceMode.Light);</description>
88+
/// </item>
89+
/// </list>
90+
/// Your application should then always use <see cref="ShouldUseDarkColorsAsync"/> to determine what CSS to apply.
91+
/// </summary>
92+
/// <param name="themeSource">The new ThemeSource.</param>
93+
public void SetThemeSource(ThemeSourceMode themeSourceMode)
94+
{
95+
var themeSource = themeSourceMode.GetDescription();
96+
97+
BridgeConnector.Socket.Emit("nativeTheme-themeSource", themeSource);
98+
}
99+
100+
/// <summary>
101+
/// A <see cref="ThemeSourceMode"/> property that can be <see cref="ThemeSourceMode.System"/>, <see cref="ThemeSourceMode.Light"/> or <see cref="ThemeSourceMode.Dark"/>. It is used to override (<seealso cref="SetThemeSource"/>) and
102+
/// supercede the value that Chromium has chosen to use internally.
103+
/// </summary>
104+
public Task<ThemeSourceMode> GetThemeSourceAsync()
105+
{
106+
var taskCompletionSource = new TaskCompletionSource<ThemeSourceMode>();
107+
108+
BridgeConnector.Socket.On("nativeTheme-themeSource-getCompleted", (themeSource) =>
109+
{
110+
BridgeConnector.Socket.Off("nativeTheme-themeSource-getCompleted");
111+
112+
var themeSourceValue = (ThemeSourceMode)Enum.Parse(typeof(ThemeSourceMode), (string)themeSource, true);
113+
114+
taskCompletionSource.SetResult(themeSourceValue);
115+
});
116+
117+
BridgeConnector.Socket.Emit("nativeTheme-themeSource-get");
118+
119+
return taskCompletionSource.Task;
120+
}
121+
122+
/// <summary>
123+
/// A <see cref="bool"/> for if the OS / Chromium currently has a dark mode enabled or is
124+
/// being instructed to show a dark-style UI. If you want to modify this value you
125+
/// should use <see cref="SetThemeSource"/>.
38126
/// </summary>
39-
/// <returns></returns>
40127
public Task<bool> ShouldUseDarkColorsAsync()
41128
{
42129
var taskCompletionSource = new TaskCompletionSource<bool>();
@@ -51,5 +138,75 @@ public Task<bool> ShouldUseDarkColorsAsync()
51138

52139
return taskCompletionSource.Task;
53140
}
141+
142+
/// <summary>
143+
/// A <see cref="bool"/> for if the OS / Chromium currently has high-contrast mode enabled or is
144+
/// being instructed to show a high-contrast UI.
145+
/// </summary>
146+
public Task<bool> ShouldUseHighContrastColorsAsync()
147+
{
148+
var taskCompletionSource = new TaskCompletionSource<bool>();
149+
150+
BridgeConnector.Socket.On("nativeTheme-shouldUseHighContrastColors-completed", (shouldUseHighContrastColors) => {
151+
BridgeConnector.Socket.Off("nativeTheme-shouldUseHighContrastColors-completed");
152+
153+
taskCompletionSource.SetResult((bool)shouldUseHighContrastColors);
154+
});
155+
156+
BridgeConnector.Socket.Emit("nativeTheme-shouldUseHighContrastColors");
157+
158+
return taskCompletionSource.Task;
159+
}
160+
161+
/// <summary>
162+
/// A <see cref="bool"/> for if the OS / Chromium currently has an inverted color scheme or is
163+
/// being instructed to use an inverted color scheme.
164+
/// </summary>
165+
public Task<bool> ShouldUseInvertedColorSchemeAsync()
166+
{
167+
var taskCompletionSource = new TaskCompletionSource<bool>();
168+
169+
BridgeConnector.Socket.On("nativeTheme-shouldUseInvertedColorScheme-completed", (shouldUseInvertedColorScheme) => {
170+
BridgeConnector.Socket.Off("nativeTheme-shouldUseInvertedColorScheme-completed");
171+
172+
taskCompletionSource.SetResult((bool)shouldUseInvertedColorScheme);
173+
});
174+
175+
BridgeConnector.Socket.Emit("nativeTheme-shouldUseInvertedColorScheme");
176+
177+
return taskCompletionSource.Task;
178+
}
179+
180+
/// <summary>
181+
/// Emitted when something in the underlying NativeTheme has changed. This normally means that either the value of <see cref="ShouldUseDarkColorsAsync"/>,
182+
/// <see cref="ShouldUseHighContrastColorsAsync"/> or <see cref="ShouldUseInvertedColorSchemeAsync"/> has changed. You will have to check them to determine which one has changed.
183+
/// </summary>
184+
public event Action Updated
185+
{
186+
add
187+
{
188+
if (_updated == null)
189+
{
190+
BridgeConnector.Socket.On("nativeTheme-updated" + GetHashCode(), () =>
191+
{
192+
_updated();
193+
});
194+
195+
BridgeConnector.Socket.Emit("register-nativeTheme-updated-event", GetHashCode());
196+
}
197+
_updated += value;
198+
}
199+
remove
200+
{
201+
_updated -= value;
202+
203+
if (_updated == null)
204+
{
205+
BridgeConnector.Socket.Off("nativeTheme-updated" + GetHashCode());
206+
}
207+
}
208+
}
209+
210+
private event Action _updated;
54211
}
55-
}
212+
}

ElectronNET.Host/api/nativeTheme.js

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ElectronNET.Host/api/nativeTheme.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ElectronNET.Host/api/nativeTheme.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,32 @@ export = (socket: SocketIO.Socket) => {
99

1010
electronSocket.emit('nativeTheme-shouldUseDarkColors-completed', shouldUseDarkColors);
1111
});
12-
};
12+
13+
socket.on('nativeTheme-shouldUseHighContrastColors', () => {
14+
const shouldUseHighContrastColors = nativeTheme.shouldUseHighContrastColors;
15+
16+
electronSocket.emit('nativeTheme-shouldUseHighContrastColors-completed', shouldUseHighContrastColors);
17+
});
18+
19+
socket.on('nativeTheme-shouldUseInvertedColorScheme', () => {
20+
const shouldUseInvertedColorScheme = nativeTheme.shouldUseInvertedColorScheme;
21+
22+
electronSocket.emit('nativeTheme-shouldUseInvertedColorScheme-completed', shouldUseInvertedColorScheme);
23+
});
24+
25+
socket.on('nativeTheme-themeSource-get', () => {
26+
const themeSource = nativeTheme.themeSource;
27+
28+
electronSocket.emit('nativeTheme-themeSource-getCompleted', themeSource);
29+
});
30+
31+
socket.on('nativeTheme-themeSource', (themeSource) => {
32+
nativeTheme.themeSource = themeSource;
33+
});
34+
35+
socket.on('register-nativeTheme-updated-event', (id) => {
36+
nativeTheme.on('updated', () => {
37+
electronSocket.emit('nativeTheme-updated' + id);
38+
});
39+
});
40+
};

0 commit comments

Comments
 (0)