Skip to content

Commit a70ef09

Browse files
author
Eduardo Flores
authored
Improve error handling (#59)
* Error handling - Added `Error` struct. - Added `Result` return type to methods. - Added justfile to facilitate building multiple platforms. - Updated README.md - Removed busy loops
1 parent 28f07bd commit a70ef09

26 files changed

Lines changed: 251 additions & 393 deletions

Cargo.toml

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
[package]
22
name = "dark-light"
33
version = "2.0.0"
4-
authors = ["Corey Farwell <[email protected]>"]
5-
edition = "2018"
4+
authors = [
5+
"Corey Farwell <[email protected]>",
6+
"Eduardo Flores <[email protected]>",
7+
]
8+
edition = "2021"
69
license = "MIT/Apache-2.0"
7-
repository = "https://github.com/frewsxcv/rust-dark-light"
10+
repository = "https://github.com/rust-dark-light/rust-dark-light"
811
description = "Detect if dark mode or light mode is enabled"
912
readme = "README.md"
1013
build = "build.rs"
1114

12-
[[example]]
13-
name = "sync"
14-
path = "examples/sync.rs"
15-
required-features = ["sync"]
16-
17-
[features]
18-
sync = []
19-
2015
[dependencies]
2116
futures-lite = "2.3.0"
2217
log = "0.4.22"

README.md

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
<br>
88
</div>
99

10-
Supports macOS, Windows, Linux, BSDs, and WASM. On Linux the XDG Desktop Portal D-Bus API is checked for the `color-scheme` preference, which works in Flatpak sandboxes without needing filesystem access.
10+
Supports macOS, Windows, Linux, BSDs, and WebAssembly.
11+
12+
On Linux the XDG Desktop Portal D-Bus API is checked for the `color-scheme` preference, which works in Flatpak sandboxes without needing filesystem access.
1113

1214
[API Documentation](https://docs.rs/dark-light/)
1315

@@ -16,70 +18,39 @@ Supports macOS, Windows, Linux, BSDs, and WASM. On Linux the XDG Desktop Portal
1618
### Detect current theme mode
1719
You can detect the current mode by using the `detect` function. This function returns a `Mode` value.
1820
```rust
19-
use dark_light::Mode;
20-
21-
let mode = dark_light::detect().await;
22-
23-
match mode {
24-
Mode::Dark => {},
25-
Mode::Light => {},
26-
Mode::Default => {},
21+
fn main() -> Result<(), dark_light::Error> {
22+
match dark_light::detect()? {
23+
dark_light::Mode::Dark => println!("Dark mode"),
24+
dark_light::Mode::Light => println!("Light mode"),
25+
dark_light::Mode::Unspecified => println!("Unspecified"),
26+
}
27+
Ok(())
2728
}
2829
```
2930

3031
### Subscribe to system theme changes
3132
You can subscribe to system theme changes by using the `subscribe` function. This function returns a stream of `Mode` values. The stream will emit a new value whenever the system theme changes.
3233

34+
> [!WARNING]
35+
> The `subscribe` function is not yet supported on macOS, Windows, and WebAssembly.
36+
> Using it will result in an empty stream.
37+
3338
```rust
34-
use dark_light::Mode;
39+
use futures_lite::StreamExt;
3540

3641
#[tokio::main]
37-
async fn main() {
38-
let mut stream = dark_light::subscribe().await;
42+
async fn main() -> Result<(), dark_light::Error> {
43+
let mut stream = dark_light::subscribe().await?;
3944
while let Some(mode) = stream.next().await {
40-
match mode {
41-
Mode::Dark => {},
42-
Mode::Light => {},
43-
Mode::Default => {},
44-
}
45+
println!("System mode changed: {:?}", mode);
4546
}
47+
Ok(())
4648
}
4749
```
4850

49-
This crate is asynchronous by default, but can be used in a synchronous manner by enabling the `sync` feature and prefixing the methods with `sync::`.
50-
51-
```rust
52-
let mode = dark_light::sync::detect();
53-
let rx = dark_light::sync::subscribe();
54-
```
55-
56-
> If you are upgrading this crate, you may update your code to use the async API or alternatively, you can use the `sync` feature to use the synchronous version of the methods.
57-
58-
## Example
59-
60-
Async:
61-
```
62-
cargo run --example async
63-
```
64-
65-
Sync
66-
```
67-
cargo run --example sync
68-
```
69-
70-
## Test
71-
To test the crate, run the following command:
72-
```
73-
cargo test --doc --all-features
74-
```
75-
7651
## License
7752

78-
Licensed under either of
53+
Licensed under either of the following licenses:
7954

8055
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
81-
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
82-
83-
at your option.
84-
85-
56+
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

examples/async.rs

Lines changed: 0 additions & 19 deletions
This file was deleted.

examples/detect.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn main() -> Result<(), dark_light::Error> {
2+
match dark_light::detect() {
3+
Ok(_) => todo!(),
4+
Err(err) => println!("Error: {}", err),
5+
}
6+
match dark_light::detect()? {
7+
dark_light::Mode::Dark => println!("Dark mode"),
8+
dark_light::Mode::Light => println!("Light mode"),
9+
dark_light::Mode::Unspecified => println!("Unspecified"),
10+
}
11+
Ok(())
12+
}

examples/notify.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

examples/subscribe.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use futures_lite::StreamExt;
2+
3+
#[tokio::main]
4+
async fn main() -> Result<(), dark_light::Error> {
5+
let mut stream = dark_light::subscribe().await?;
6+
while let Some(mode) = stream.next().await {
7+
println!("System mode changed: {:?}", mode);
8+
}
9+
Ok(())
10+
}

examples/sync.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

justfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
build:
2+
echo "Building for Linux..."
3+
cargo build --target x86_64-unknown-linux-gnu
4+
echo "Building for macOS..."
5+
cargo build --target aarch64-apple-darwin
6+
echo "Building for Windows..."
7+
cargo build --target x86_64-pc-windows-gnu
8+
echo "Building for wasm..."
9+
cargo build --target wasm32-unknown-unknown
10+
11+
test:
12+
cargo test --doc
13+
14+
doc-linux:
15+
cargo doc --no-deps --open --target x86_64-unknown-linux-gnu
16+
17+
doc-macos:
18+
cargo doc --no-deps --open --target aarch64-apple-darwin
19+
20+
doc-windows:
21+
cargo doc --no-deps --open --target x86_64-pc-windows-gnu
22+
23+
doc-wasm:
24+
cargo doc --no-deps --open --target wasm32-unknown-unknown
25+
26+
example-linux:
27+
echo "Building examples for Linux..."
28+
cargo build --example detect --target x86_64-unknown-linux-gnu
29+
cargo build --example subscribe --target x86_64-unknown-linux-gnu
30+
example-macos:
31+
echo "Building examples for macOS..."
32+
cargo build --example detect --target aarch64-apple-darwin
33+
cargo build --example subscribe --target aarch64-apple-darwin
34+
example-windows:
35+
echo "Building examples for Windows..."
36+
cargo build --example detect --target x86_64-pc-windows-gnu
37+
cargo build --example subscribe --target x86_64-pc-windows-gnu
38+
example-wasm:
39+
echo "Building examples for wasm..."
40+
cargo build --example detect --target wasm32-unknown-unknown
41+
cargo build --example subscribe --target wasm32-unknown-unknown

src/error.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::fmt::Display;
2+
3+
/// An error that can occur when detecting the system theme mode.
4+
#[derive(Debug)]
5+
pub enum Error {
6+
/// If an I/O error occurs.
7+
Io(std::io::Error),
8+
/// If the system theme mode could not be detected.
9+
DetectionFailed,
10+
11+
#[cfg(target_os = "linux")]
12+
/// If the XDG Desktop Portal could not be communicated with.
13+
XdgDesktopPortal(ashpd::Error),
14+
15+
/// Failed to get persistent domain for Apple Global Domain
16+
#[cfg(target_os = "macos")]
17+
PersistentDomainFailed,
18+
/// Failed to get AppleInterfaceStyle
19+
#[cfg(target_os = "macos")]
20+
AppleInterfaceStyleFailed,
21+
22+
#[cfg(target_arch = "wasm32")]
23+
/// If the window could not be found.
24+
WindowNotFound,
25+
#[cfg(target_arch = "wasm32")]
26+
/// If the media query could not be executed.
27+
MediaQueryFailed,
28+
#[cfg(target_arch = "wasm32")]
29+
/// If the media query is not supported.
30+
MediaQueryNotSupported,
31+
}
32+
33+
impl Display for Error {
34+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35+
match self {
36+
Error::Io(error) => write!(f, "I/O error: {}", error),
37+
Error::DetectionFailed => write!(f, "Failed to detect system theme mode"),
38+
#[cfg(target_os = "linux")]
39+
Error::XdgDesktopPortal(err) => write!(f, "XDG Desktop Portal error: {}", err),
40+
#[cfg(target_os = "macos")]
41+
Error::PersistentDomainFailed => {
42+
write!(f, "Failed to get persistent domain for Apple Global Domain")
43+
}
44+
#[cfg(target_os = "macos")]
45+
Error::AppleInterfaceStyleFailed => write!(f, "Failed to get AppleInterfaceStyle"),
46+
#[cfg(target_arch = "wasm32")]
47+
Error::WindowNotFound => write!(f, "Window not found"),
48+
#[cfg(target_arch = "wasm32")]
49+
Error::MediaQueryFailed => write!(f, "Media query failed"),
50+
#[cfg(target_arch = "wasm32")]
51+
Error::MediaQueryNotSupported => write!(f, "Media query not supported"),
52+
}
53+
}
54+
}
55+
56+
impl std::error::Error for Error {}
57+
58+
impl From<std::io::Error> for Error {
59+
fn from(error: std::io::Error) -> Self {
60+
Error::Io(error)
61+
}
62+
}
63+
64+
#[cfg(target_os = "linux")]
65+
impl From<ashpd::Error> for Error {
66+
fn from(error: ashpd::Error) -> Self {
67+
Error::XdgDesktopPortal(error)
68+
}
69+
}

0 commit comments

Comments
 (0)