Completed APIs from #956

This commit is contained in:
Florian Rappl
2026-09-04 16:57:44 +02:00
parent fffd7dfb79
commit a04ca0b9bc
6 changed files with 150 additions and 1 deletions

View File

@@ -17,6 +17,8 @@
- Added `WebContents.InsertCSSAsync` and `WebContents.RemoveInsertedCSSAsync` for dynamic CSS (#956)
- Added `WebContents` editing and selection APIs (undo, redo, cut, copy, paste, insert text, select, ...) (#956)
- Added `WebContents.FindInPageAsync`, `WebContents.StopFindInPage` and the `OnFoundInPage` event (#956)
- Added `WebContents` audio events `OnAudioStateChanged`, `OnMediaStartedPlaying` and `OnMediaPaused` (#956)
- Added `WebContents.ScrollToTop` and `WebContents.ScrollToBottom` (#956)
- Added target framework customization (#1095) @epsnm
- Added configurable Electron root directory for custom packaging layouts (#1106) @DYH1319
- Added ability for `custom_main.js` to modify command line switches (#1029) @AeonSake

View File

@@ -162,6 +162,18 @@ Loads the given HTML file, relative to the root of the application.
- `filePath` - Path to the HTML file
- `options` - Optional `Query`, `Search` and `Hash` parts of the resulting URL
#### 🧊 `void SetAudioMuted(bool muted)`
Mutes or unmutes the audio on the current web page.
#### 🧊 `Task<bool> IsAudioMutedAsync()`
Whether this page has been muted.
#### 🧊 `Task<bool> IsCurrentlyAudibleAsync()`
Whether audio is currently playing.
#### 🧊 `Task<string> GetUserAgentAsync()` / `void SetUserAgent(string userAgent)`
Gets or overrides the user agent for this web page.
#### 🧊 `Task<bool> IsLoadingAsync()`
Whether the web page is still loading resources.
@@ -192,6 +204,9 @@ Copies the image at the given position to the clipboard.
#### 🧊 `void SelectAll()` / `void Unselect()` / `void CenterSelection()`
Selects all content, clears the selection, or scrolls to the current selection.
#### 🧊 `void ScrollToTop()` / `void ScrollToBottom()`
Scrolls to the top or the bottom of the current web page.
#### 🧊 `void AdjustSelection(AdjustSelectionOptions options)`
Adjusts the start and end points of the current text selection by the given amounts. Negative amounts move towards the beginning of the document.
@@ -250,6 +265,15 @@ Emitted when the user changes the zoom level using the mouse wheel or the keyboa
#### ⚡ `OnFoundInPage`
Emitted when a result is available for a `FindInPageAsync` request. The handler receives a `FoundInPageResult`.
#### ⚡ `OnAudioStateChanged`
Emitted when media becomes audible or inaudible. The handler receives `true` if one or more frames or child web contents are emitting audio.
#### ⚡ `OnMediaStartedPlaying`
Emitted when media starts playing.
#### ⚡ `OnMediaPaused`
Emitted when media is paused or done playing.
## Usage Examples
### Page Loading
@@ -446,6 +470,23 @@ webContents.OnFoundInPage += (result) =>
var requestId = await webContents.FindInPageAsync("electron", new FindInPageOptions { MatchCase = false });
```
### Audio
```csharp
webContents.SetAudioMuted(true);
var muted = await webContents.IsAudioMutedAsync();
var audible = await webContents.IsCurrentlyAudibleAsync();
webContents.OnAudioStateChanged += (isAudible) =>
{
Console.WriteLine(isAudible ? "Page started emitting audio" : "Page went silent");
};
webContents.OnMediaStartedPlaying += () => Console.WriteLine("Media playing");
webContents.OnMediaPaused += () => Console.WriteLine("Media paused");
```
## Related APIs
- [Electron.WindowManager](WindowManager.md) - Windows containing web contents

View File

@@ -131,6 +131,34 @@ public class WebContents : ApiBase
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when media becomes audible or inaudible. The parameter is true if one or more
/// frames or child web contents are emitting audio.
/// </summary>
public event Action<bool> OnAudioStateChanged
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when media starts playing.
/// </summary>
public event Action OnMediaStartedPlaying
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when media is paused or done playing.
/// </summary>
public event Action OnMediaPaused
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
internal WebContents(int id)
{
Id = id;
@@ -611,6 +639,22 @@ public class WebContents : ApiBase
BridgeConnector.Socket.Emit("webContents-centerSelection", Id);
}
/// <summary>
/// Scrolls to the top of the current web page.
/// </summary>
public void ScrollToTop()
{
BridgeConnector.Socket.Emit("webContents-scrollToTop", Id);
}
/// <summary>
/// Scrolls to the bottom of the current web page.
/// </summary>
public void ScrollToBottom()
{
BridgeConnector.Socket.Emit("webContents-scrollToBottom", Id);
}
/// <summary>
/// Inserts text to the focused element.
/// </summary>

View File

@@ -125,6 +125,27 @@ module.exports = (socket) => {
electronSocket.emit("webContents-foundInPage" + id, result);
});
});
socket.on("register-webContents-audioStateChanged", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("audio-state-changed");
browserWindow.webContents.on("audio-state-changed", (event) => {
electronSocket.emit("webContents-audioStateChanged" + id, event.audible);
});
});
socket.on("register-webContents-mediaStartedPlaying", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("media-started-playing");
browserWindow.webContents.on("media-started-playing", () => {
electronSocket.emit("webContents-mediaStartedPlaying" + id);
});
});
socket.on("register-webContents-mediaPaused", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("media-paused");
browserWindow.webContents.on("media-paused", () => {
electronSocket.emit("webContents-mediaPaused" + id);
});
});
socket.on("webContents-openDevTools", (id, options) => {
if (options) {
getWindowById(id).webContents.openDevTools(options);
@@ -491,6 +512,12 @@ module.exports = (socket) => {
socket.on("webContents-centerSelection", (id) => {
getWindowById(id).webContents.centerSelection();
});
socket.on("webContents-scrollToTop", (id) => {
getWindowById(id).webContents.scrollToTop();
});
socket.on("webContents-scrollToBottom", (id) => {
getWindowById(id).webContents.scrollToBottom();
});
socket.on("webContents-insertText", async (id, text) => {
await getWindowById(id).webContents.insertText(text);
electronSocket.emit("webContents-insertText-completed" + id);

File diff suppressed because one or more lines are too long

View File

@@ -121,6 +121,33 @@ export = (socket: Socket) => {
});
});
socket.on("register-webContents-audioStateChanged", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("audio-state-changed");
browserWindow.webContents.on("audio-state-changed", (event) => {
electronSocket.emit("webContents-audioStateChanged" + id, event.audible);
});
});
socket.on("register-webContents-mediaStartedPlaying", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("media-started-playing");
browserWindow.webContents.on("media-started-playing", () => {
electronSocket.emit("webContents-mediaStartedPlaying" + id);
});
});
socket.on("register-webContents-mediaPaused", (id) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.removeAllListeners("media-paused");
browserWindow.webContents.on("media-paused", () => {
electronSocket.emit("webContents-mediaPaused" + id);
});
});
socket.on("webContents-openDevTools", (id, options) => {
if (options) {
getWindowById(id).webContents.openDevTools(options);
@@ -682,6 +709,14 @@ export = (socket: Socket) => {
getWindowById(id).webContents.centerSelection();
});
socket.on("webContents-scrollToTop", (id) => {
getWindowById(id).webContents.scrollToTop();
});
socket.on("webContents-scrollToBottom", (id) => {
getWindowById(id).webContents.scrollToBottom();
});
socket.on("webContents-insertText", async (id, text) => {
await getWindowById(id).webContents.insertText(text);
electronSocket.emit("webContents-insertText-completed" + id);