Commit Graph

124 Commits

Author SHA1 Message Date
Emil Ernerfeldt 10571e9da5
`eframe::Result` is now short for `eframe::Result<()>` (#4706) 2024-06-25 13:31:42 +02:00
Nathan Adams 87021d3fbd
`egui_extras`: Make `serde` an optional feature (#4641)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

All the other crates in egui have serde as an optional dependency -
which is great! But sadly egui_extras unconditionally includes it, which
adds a bunch of code to stuff that may not care for it. This PR gates
serde support behind a new `serde` feature.

This is a breaking change; if that's undesirable then we can add it as a
default feature instead, though that wouldn't match any of the other
crates.
2024-06-18 22:27:48 +02:00
Emil Ernerfeldt 814ad0783c
Update to wgpu 0.20 (#4560)
* this PR reverts https://github.com/emilk/egui/pull/4559
* and re-applies https://github.com/emilk/egui/pull/4433

Before we merge, we're waiting for a wgpu 0.20.1 patch-release of

* https://github.com/gfx-rs/wgpu/pull/5681

---------

Co-authored-by: Andreas Reich <r_andreas2@web.de>
2024-06-13 15:00:23 +02:00
Emil Ernerfeldt 5eee463851 Replace some `...` with `…` 2024-05-29 11:48:50 +02:00
Emil Ernerfeldt 942fe4ab31
Support returning errors when creating the app (#4565)
The closure passed to `eframe::run_native` now returns a `Result`,
allowing you to return an error during app creation, which will be
returned to the caller of `run_native`.

This means you need to wrap your `Box::new(MyApp::new(…))` in an
`Ok(…)`.

* Closes https://github.com/emilk/egui/issues/4474
2024-05-28 21:59:19 +02:00
Emil Ernerfeldt 54429e0549
Revert update to wgpu 0.20 => downgrade to wgpu 0.19.1 (#4559)
0.20 has a bunch of bugs that will be fixed by:

* https://github.com/gfx-rs/wgpu/pull/5681

At Rerun, we don't want to wait for the wgpu 0.20.1 patch release before
we update egui, so we will temporarily downgrade to wgpu 0.19

After reverting I'll open a new PR that will update to 0.20 again, with
the intention of merging that once 0.20.1 is released.
2024-05-28 14:40:43 +02:00
Antoine Beyeler bcd91f27a1
Add support for text truncation to `egui::Style` (#4556)
* Closes #4473

This PR introduce `Style::wrap_mode`, which adds support for text
truncation in addition to text wrapping. This PR also update some width
calculation of the ComboBox.

#### Core

- Add `egui::TextWrapMode` (pure enum with `Extend`, `Wrap`, `Truncate`)
- Add `Style::wrap_mode: Option<tTextWrapMode>`
- **DEPRECATED**: `Style::wrap`, use `Style::wrap_mode` instead.
- Add `Ui::wrap_mode()` to return the wrap mode to use in the current
ui. If specified in `Style`, return it. Otherwise, return
`TextWrapMode::Wrap` for vertical layout and wrapping horizontal layout,
and `TextWrapMode::Extend` otherwise.
- **DEPRECATED**: `Ui::wrap_text()`, use `Ui::wrap_mode` instead.

#### Widget

- Update the width calculation of the `ComboBox` button (_not_ its popup
menu).
- Now, `ComboBox::width()` (defaulting to `Spacing::combo_width`) is
always considered a minimum width and will extend the `Ui`, regardless
of the selected text width and wrap mode.
- Introduce `ComboBox::wrap_mode`, which overrides `Ui::wrap_mode` for
the selected text layout.
- Note: since `ComboBox` uses `ui.horizontal` internally, the default
wrap mode is always `TextWrapMode::Extend`, regardless of the caller's
`Ui`'s layout.
- The `ComboBox` button no longer extend to `ui.available_width()` with
wrapping is enabled.
- **BREAKING**: `ComboBox::wrap()` no longer has a `bool` argument and
is now a short-hand for `ComboBox::wrap_mode(TextWrapMode::Wrap)`.
- Added `ComboBox::truncate()` as short-hand for
`ComboBox::wrap_mode(TextWrapMode::Truncate)`.
- Update `Label`
  - Add `Label::wrap_mode()` to specify the text wrap mode.
- **BREAKING**: `Label::wrap()` no longer has a `bool` argument and is
now a short-hand for `Label::wrap_mode(TextWrapMode::Wrap)`.
- **BREAKING**: `Label::truncate()` no longer has a `bool` argument and
is now a short-hand for `Label::wrap_mode(TextWrapMode::Truncate)`.
- Update `Button`
  - Add `Button::wrap_mode()` to specify the text wrap mode.
- **BREAKING**: `Button::wrap()` no longer has a `bool` argument and is
now a short-hand for `Button::wrap_mode(TextWrapMode::Wrap)`.
- Added `Button::truncate()` as short-hand for
`Button::wrap_mode(TextWrapMode::Truncate)`.

#### Low-level

- **BREAKING**: `WidgetText::into_galley()` now takes an
`Option<TextWrapMode>` instead of a `Option<bool>` argument.
- **BREAKING**: `WidgetText::into_galley_impl(()` now takes a
`TextWrapping` argument instead of `wrap: bool` and `availalbe_width:
f32` arguments.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-05-28 13:10:41 +02:00
Varphone Wong 6f59a14c4d
Add `Options::reduce_texture_memory` to free up RAM (#4431)
## Summary

This PR introduces a new configuration option `reduce_texture_memory` in
`egui`.

## Changes

- Added `reduce_texture_memory` option in `egui`. When set to `true`,
`egui` will discard the loaded image data after the texture is uploaded
to the GPU, reducing memory usage. This is beneficial when handling a
large number of images and retaining the image data is unnecessary,
potentially saving substantial memory. However, this makes it impossible
to serialize the loaded images or render on non-GPU systems. Default is
`false`.

## Impact

This new configuration option gives users more control over their memory
usage, especially when dealing with a large number or large resolution
of images. It allows users to optimize their applications based on their
specific needs and constraints.
2024-05-28 09:13:43 +02:00
Oscar Gustafsson c1eb3f884d
Move dependencies to workspace (#4495)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

Inspired by:

44d65f41ac/Cargo.toml (L65)

I took the liberty of removing that comment since I *think* that I got
all "relevant" ones (showing up more than once, sort of).
2024-05-14 11:02:49 +02:00
Emil Ernerfeldt 44d65f41ac
Update `image` crate to 0.25 (#4160)
To not produce duplicating deps in Rerun
(https://github.com/rerun-io/rerun/pull/5280) I suggest we wait with
merging this until these crates have updated to `image` 0.25:
* [x] [`arboard`](https://crates.io/crates/arboard)
* [x] [`gltf`](https://crates.io/crates/gltf)
2024-05-13 13:35:15 +02:00
Emil Ernerfeldt f19f99180e
Remove `extra_asserts` and `extra_debug_asserts` feature flags (#4478)
Removes `egui_assert` etc and replaces it with normal `debug_assert`
calls.

Previously you could opt-in to more runtime checks using feature flags.
Now these extra runtime checks are always enabled for debug builds.

You are most likely to encounter them if you use negative sizes or NaNs
or other similar bugs.
These usually indicate bugs in user space.
2024-05-10 19:39:08 +02:00
Emil Ernerfeldt ded8dbd45b
Fix some clippy warning from Rust 1.78.0 (#4444) 2024-05-02 17:04:25 +02:00
Simon Niedermayr c9b24d5a5c
Update to wgpu 0.20 (#4433)
updates the wgpu version to 0.20 and changes the API calls accordingly. 
I had to update wasm-bindgen to "0.2.92". Otherwise, I got this error
for the demo app:
```
error: failed to select a version for `wasm-bindgen`.
    ... required by package `js-sys v0.3.69`
    ... which satisfies dependency `js-sys = "^0.3.69"` of package `eframe v0.27.2 (/home/user/Projects/egui/crates/eframe)`
    ... which satisfies path dependency `eframe` (locked to 0.27.2) of package `confirm_exit v0.1.0 (/home/user/Projects/egui/examples/confirm_exit)`
versions that meet the requirements `^0.2.92` are: 0.2.92

all possible versions conflict with previously selected packages.

  previously selected package `wasm-bindgen v0.2.90`
    ... which satisfies dependency `wasm-bindgen = "=0.2.90"` of package `egui_demo_app v0.27.2 (/home/user/Projects/egui/crates/egui_demo_app)`

failed to select a version for `wasm-bindgen` which could resolve this conflict
```

Why is it locked to this version right now?

I ran the tests, checked the web demo and my own projects, and
everything seems to work fine with wgpu 0.20.

---------

Co-authored-by: Andreas Reich <r_andreas2@web.de>
2024-04-30 11:47:12 +02:00
Emil Ernerfeldt 2f508d6a61
Replace cargo-cranky with workspace lints (#4413)
Replace `cargo-cranky` (which has served us well) with workspace lints
2024-04-25 17:24:50 +02:00
Emil Ernerfeldt 48ecf01e11
Rename "Color test" to "Rendering test", and restructure it slightly (#4298)
Put the pixel-alignment test first, and hide the color test under a
collapsing header.

<img width="743" alt="Screenshot 2024-04-01 at 13 01 43"
src="https://github.com/emilk/egui/assets/1148717/8e7108ab-63c8-470f-9c21-83181287969b">
2024-04-01 13:08:52 +02:00
Emil Ernerfeldt 1354c3e19a
Make the code example demo narrow enough to fit on mobile (#4281)
I think it is a good example, and so I want to open it by default, but
for that it needs to work on mobile.

Hopefully this doesn't make it too cryptic

<img width="415" alt="image"
src="https://github.com/emilk/egui/assets/1148717/83d881fa-675e-4659-bd21-14abcb79fe46">
2024-03-30 17:51:44 +01:00
Emil Ernerfeldt 3dba73e63e
Improve the UI for changing the egui theme (#4257)
I added a new demo - a `Frame` editor:

![frame-editor](https://github.com/emilk/egui/assets/1148717/d0bec169-c211-45a3-9f53-5059fb8fc224)

This whole menu is now just a a bit nicer to use:
<img width="406" alt="Screenshot 2024-03-28 at 09 49 16"
src="https://github.com/emilk/egui/assets/1148717/32d12067-7cf0-4312-aa12-42909a5ed5ac">
2024-03-28 10:09:28 +01:00
Colin Kinloch 287a550b90
egui demo: Add drop down to resize the window (#4197)
An alternative to the "Phone Size" button useful for testing
`ViewportCommand::InnerSize`.

I created this to make it easy to debug
https://github.com/emilk/egui/issues/4196 there are more details there.
2024-03-25 13:11:39 +01:00
Giantblargg b8048572e8
Add API for raw mouse motion (#4063)
Raw mouse movement is unaccelerated and unclamped by screen boundaries,
and does not relate to any position on the screen.
It is useful in certain situations such as draggable values and 3D
cameras, where screen position does not matter.


https://github.com/emilk/egui/assets/1700581/1400e6a6-0573-41b9-99a1-a9cd305aa1a3

Added `Event::MouseMoved` for integrations to supply raw mouse movement.
Added `Response:drag_motion` to get the raw mouse movement, but will
fall back to delta in case the integration does not supply it.

Nothing should be breaking, but third-party integrations that can send
`Event::MouseMoved` should be updated to do so.

Based on #1614 but updated to the current version, and with better
fallback behaviour.

* Closes #1611
* Supersedes #1614
2024-02-20 18:00:39 +01:00
Emil Ernerfeldt 6fbf7fe566
Update `ehttp` to 0.5 (#4055) 2024-02-16 10:57:54 +01:00
Emil Ernerfeldt 217e066626
Make `egui_wgpu::renderer` a private module (#3979)
All its contents is exported to the top-level
2024-02-05 15:12:59 +01:00
Emil Ernerfeldt d02491425c
Put all egui crates as workspace crates (#3976)
Second attempty
2024-02-05 12:59:49 +01:00
Emil Ernerfeldt bcebfecb84
Use more workspace dependencies (#3975) 2024-02-05 12:43:58 +01:00
StratusFearMe21 7a6d80cc8c
Pass `ScreenDescriptor` to `egui_wgpu::CallbackTrait::prepare` (#3960)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to add commits to your PR.
* Remember to run `cargo fmt` and `cargo cranky`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

`glyphon` requires the screen resolution during the `prepare` stage, and
passing that to the callback's `prepare` function seems pretty trivial.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-02-05 11:17:21 +01:00
Emil Ernerfeldt 8f2c8664e7
Emilk/revert workspace deps (#3942)
* Closes https://github.com/emilk/egui/issues/3941

Workspace dependencies can be annoying.

If you don't set them to `default-features=false`, then you cannot opt
out of their default features anywhere else, and get warnings if you
try.

So you set `default-features=false`, and then you need to manually opt
in to the default features everywhere else.
Or, as in my case, don't.

I don't have the energy to do this tonight, so I'll just revert.
2024-02-01 21:29:48 +01:00
Emil Ernerfeldt 00cd671ad8 Use workspace dependencies for the egui crates 2024-02-01 20:25:31 +01:00
Emil Ernerfeldt 948db61a8a
Update to puffin 0.19 (#3940)
…and some other smaller crate updates
2024-02-01 20:15:11 +01:00
Emil Ernerfeldt dda9f79838 Remove `version` field for path-dependencies 2024-02-01 20:11:40 +01:00
YgorSouza d72f92c41d
Add `x11` and `wayland` features to egui-wgpu and egui_glow (#3909)
This allows them to build correctly on Linux by passing one or both of
the features alongside `winit`.

Closes #3492
Closes #2286
2024-01-30 16:55:55 +01:00
Emil Ernerfeldt ab39420c29
Much more accurate `cpu_usage` timing (#3913)
`frame.info.cpu_usage` now includes time for tessellation and rendering,
but excludes vsync and context switching.
2024-01-29 19:12:16 +01:00
Emil Ernerfeldt b766a48fa7
Update wgpu to 0.19 (#3824)
* Closes https://github.com/emilk/egui/issues/3675

---------

Co-authored-by: Andreas Reich <r_andreas2@web.de>
Co-authored-by: Mingun <Alexander_Sergey@mail.ru>
2024-01-19 10:14:13 +01:00
Emil Ernerfeldt f01d337fa8
Update to ehttp 0.4 (#3834) 2024-01-17 15:39:28 +01:00
Emil Ernerfeldt 5d2e192927
Selectable text in Labels (#3814)
* Closes https://github.com/emilk/egui/issues/3804

Add ability to select the text in labels with mouse-drag, double-click,
and keyboard (once clicked).
Hit Cmd+C to copy the text. If everything of a label with elided text is
selected, the copy command will copy the full non-elided text. IME and
accesskit _should_ work, but is untested.

You can control wether or not text in labels is selected globally in
`style.interaction.selectable_labels` or on a per-label basis in
`Label::selectable`. The default is ON.

This also cleans up the `TextEdit` code somewhat, fixing a couple
smaller bugs along the way.

This does _not_ implement selecting text across multiple widgets. Text
selection is only supported within a single `Label`, `TextEdit`, `Link`
or `Hyperlink`.


![label-text-selection](https://github.com/emilk/egui/assets/1148717/c161e819-50da-4b97-9686-042e6abf3564)


## TODO
* [x] Test
2024-01-14 15:17:55 +01:00
Emil Ernerfeldt 401de05630
Use `Self` everywhere (#3787)
This turns on the clippy lint
[`clippy::use_self`](https://rust-lang.github.io/rust-clippy/v0.0.212/index.html#use_self)
and fixes it everywhere.
2024-01-08 17:41:21 +01:00
Emil Ernerfeldt 12ad9e7b36 Release 0.25.0 - Better keyboard input 2024-01-08 12:25:43 +01:00
Emil Ernerfeldt 9951fe0d36
Fix some clippy 1.75 lints (#3754) 2023-12-30 11:23:21 +01:00
Emil Ernerfeldt 0561fcaba9
Replace a special `Color32::PLACEHOLDER` with widget fallback color (#3727)
This introduces a special `Color32::PLACEHOLDER` which, during text
painting, will be replaced with `TextShape::fallback_color`.

The fallback color is mandatory to set in all text painting. Usually
this comes from the current visual style.

This lets users color only parts of a `WidgetText` (using e.g. a
`LayoutJob` or a `Galley`), where the uncolored parts (using
`Color32::PLACEHOLDER`) will be replaced by a default widget color (e.g.
blue for a hyperlink).

For instance, you can color the `⚠️`-emoji red in a piece of text red
and leave the rest of the text uncolored. The color of the rest of the
text will then depend on wether or not you put that text in a label, a
button, or a hyperlink.

Overall this simplifies a lot of complexity in the code but comes with a
few breaking changes:

* `TextShape::new`, `Shape::galley`, and `Painter::galley` now take a
fallback color by argument
* `Shape::galley_with_color` has been deprecated (use `Shape::galley`
instead)
* `Painter::galley_with_color` has been deprecated (use
`Painter::galley` instead)
* `WidgetTextGalley` is gone (use `Arc<Galley>` instead)
* `WidgetTextJob` is gone (use `LayoutJob` instead)
* `RichText::into_text_job` has been replaced with
`RichText::into_layout_job`
* `WidgetText::into_text_job` has been replaced with
`WidgetText::into_layout_job`
2023-12-22 15:09:10 +01:00
Emil Ernerfeldt c8dd3dd01a
Update dependencies (#3700)
Also disable `regex` `env_logger` feature in examples to improve compile
times.
2023-12-12 12:59:40 +01:00
Emil Ernerfeldt d17613c242 Release 0.24.1 - Bug fixes 2023-11-30 17:46:25 +01:00
Emil Ernerfeldt a1f3c71b7f
Remove dependency on `tts` (#3651)
We were using [`tts`](https://github.com/ndarilek/tts-rs) for the
web-only screen reader. This was overkill, to say the least. It is now
replaced with ten lines of `web-sys` calls.
2023-11-28 10:46:18 +01:00
Emil Ernerfeldt 8494cf854c
Update to wasm-bindgen 0.2.89 (#3644)
0.2.88 was recently yanked
2023-11-27 18:33:07 +01:00
Emil Ernerfeldt bd087ffb8d Release 0.24.0 - Multi-viewport 2023-11-23 15:56:46 +01:00
Emil Ernerfeldt 6a8b51adb5 Improve demo backend panel 2023-11-23 15:45:19 +01:00
Emil Ernerfeldt 96bc34a66d Use workspace definitions of edition,license,rust-version,version 2023-11-23 15:45:11 +01:00
Emil Ernerfeldt 63e48dc855
Introduce global `zoom_factor` (#3608)
* Closes https://github.com/emilk/egui/issues/3602

You can now zoom any egui app by pressing Cmd+Plus, Cmd+Minus or Cmd+0,
just like in a browser. This will change the current `zoom_factor`
(default 1.0) which is persisted in the egui memory, and is the same for
all viewports.
You can turn off the keyboard shortcuts with `ctx.options_mut(|o|
o.zoom_with_keyboard = false);`

`zoom_factor` can also be explicitly read/written with
`ctx.zoom_factor()` and `ctx.set_zoom_factor()`.

This redefines `pixels_per_point` as `zoom_factor *
native_pixels_per_point`, where `native_pixels_per_point` is whatever is
the native scale factor for the monitor that the current viewport is in.

This adds some complexity to the interaction with winit, since we need
to know the current `zoom_factor` in a lot of places, because all egui
IO is done in ui points. I'm pretty sure this PR fixes a bunch of subtle
bugs though that used to be in this code.

`egui::gui_zoom::zoom_with_keyboard_shortcuts` is now gone, and is no
longer needed, as this is now the default behavior.

`Context::set_pixels_per_point` is still there, but it is recommended
you use `Context::set_zoom_factor` instead.
2023-11-22 20:34:51 +01:00
Emil Ernerfeldt bfadb90d42
Update MSRV to Rust 1.72 (#3595)
Required to update to puffin 0.18
2023-11-21 17:26:35 +01:00
Emil Ernerfeldt e823491240
Update some crate dependencies (#3594)
Nothing major
2023-11-21 16:07:56 +01:00
Emil Ernerfeldt 39e60e367f
Use `egui::ViewportBuilder` in `eframe::NativeOptions` (#3572)
* Part of https://github.com/emilk/egui/issues/3556

This PR replaces a bunch of options in `eframe::NativeOptions` with
`egui::ViewportBuilder`. For instance:

``` diff
 let options = eframe::NativeOptions {
-    initial_window_size: Some(egui::vec2(320.0, 240.0)),
-    drag_and_drop_support: true,
+    viewport: egui::ViewportBuilder::default()
+        .with_inner_size([320.0, 240.0])
+        .with_drag_and_drop(true),
     centered: true,
     ..Default::default()
 };
```
2023-11-19 11:08:47 +01:00
Emil Ernerfeldt 1571027556
Replace `eframe::Frame` commands and `WindowInfo` with egui (#3564)
* Part of https://github.com/emilk/egui/issues/3556

## In short
You now almost never need to use `eframe::Frame` - instead use
`ui.input(|i| i.viewport())` for information about the current viewport
(native window), and use `ctx.send_viewport_cmd` to modify it.

## In detail

This PR removes most commands from `eframe::Frame`, and replaces them
with `ViewportCommand`.
So `frame.close()` becomes
`ctx.send_viewport_cmd(ViewportCommand::Close)`, etc.

`frame.info().window_info` is now also gone, replaced with `ui.input(|i|
i.viewport())`.

`frame.info().native_pixels_per_point` is replaced with `ui.input(|i|
i.raw.native_pixels_per_point)`.

`RawInput` now contains one `ViewportInfo` for each viewport.

Screenshots are taken with
`ctx.send_viewport_cmd(ViewportCommand::Screenshots)` and are returned
in `egui::Event` which you can check with:

``` ust
ui.input(|i| {
    for event in &i.raw.events {
        if let egui::Event::Screenshot { viewport_id, image } = event {
            // handle it here
        }
    }
});
```

### Motivation
You no longer need to pass around the `&eframe::Frame` everywhere.
This also opens the door for other integrations to use the same API of
`ViewportCommand`s.
2023-11-18 19:27:53 +01:00
Emil Ernerfeldt b27aa27e94
Add `emath::Vec2b`, replacing `egui_plot::AxisBools` (#3543)
Thanks to `impl From<bool> for Vec2b` one can now shorten some builder
calls, like:

Previous:
```rust
 egui::ScrollArea::vertical()
        .auto_shrink([false; 2])
```

New:
```rust
 egui::ScrollArea::vertical()
        .auto_shrink(false)
```
2023-11-11 21:31:36 +01:00