summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock218
-rw-r--r--src/dialogs.rs118
-rw-r--r--src/error.rs7
-rw-r--r--src/main.rs189
-rw-r--r--src/types.rs23
5 files changed, 323 insertions, 232 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 95d2a3a..b93bffa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -322,9 +322,9 @@ dependencies = [
[[package]]
name = "async-process"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb"
+checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
dependencies = [
"async-channel 2.3.1",
"async-io",
@@ -335,7 +335,7 @@ dependencies = [
"cfg-if",
"event-listener 5.4.0",
"futures-lite",
- "rustix 0.38.44",
+ "rustix 1.0.7",
"tracing",
]
@@ -352,9 +352,9 @@ dependencies = [
[[package]]
name = "async-signal"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3"
+checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
dependencies = [
"async-io",
"async-lock",
@@ -362,7 +362,7 @@ dependencies = [
"cfg-if",
"futures-core",
"futures-io",
- "rustix 0.38.44",
+ "rustix 1.0.7",
"signal-hook-registry",
"slab",
"windows-sys 0.59.0",
@@ -587,9 +587,9 @@ checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b"
[[package]]
name = "bumpalo"
-version = "3.17.0"
+version = "3.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
+checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
[[package]]
name = "bytemuck"
@@ -676,15 +676,15 @@ dependencies = [
[[package]]
name = "camino"
-version = "1.1.9"
+version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
+checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab"
[[package]]
name = "cc"
-version = "1.2.24"
+version = "1.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7"
+checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
dependencies = [
"jobserver",
"libc",
@@ -821,9 +821,9 @@ dependencies = [
[[package]]
name = "core-foundation"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
dependencies = [
"core-foundation-sys",
"libc",
@@ -855,7 +855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
dependencies = [
"bitflags 2.9.1",
- "core-foundation 0.10.0",
+ "core-foundation 0.10.1",
"core-graphics-types 0.2.0",
"foreign-types 0.5.0",
"libc",
@@ -879,7 +879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
"bitflags 2.9.1",
- "core-foundation 0.10.0",
+ "core-foundation 0.10.1",
"libc",
]
@@ -1015,7 +1015,7 @@ dependencies = [
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"web-sys",
- "winreg",
+ "winreg 0.52.0",
]
[[package]]
@@ -1197,16 +1197,16 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "embed-resource"
-version = "3.0.2"
+version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fbc6e0d8e0c03a655b53ca813f0463d2c956bc4db8138dbc89f120b066551e3"
+checksum = "e8fe7d068ca6b3a5782ca5ec9afc244acd99dd441e4686a83b1c3973aba1d489"
dependencies = [
"cc",
"memchr",
"rustc_version",
"toml",
"vswhom",
- "winreg",
+ "winreg 0.55.0",
]
[[package]]
@@ -1355,9 +1355,9 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
+checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1808,9 +1808,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.15.3"
+version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
+checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"foldhash",
]
@@ -1829,12 +1829,6 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
-[[package]]
-name = "hermit-abi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
@@ -1922,9 +1916,9 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.27.6"
+version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d"
+checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
dependencies = [
"http",
"hyper",
@@ -1954,22 +1948,28 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.12"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710"
+checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
dependencies = [
+ "base64",
"bytes",
"futures-channel",
+ "futures-core",
"futures-util",
"http",
"http-body",
"hyper",
+ "ipnet",
"libc",
+ "percent-encoding",
"pin-project-lite",
"socket2",
+ "system-configuration",
"tokio",
"tower-service",
"tracing",
+ "windows-registry",
]
[[package]]
@@ -2102,7 +2102,7 @@ dependencies = [
[[package]]
name = "iced_dialog"
version = "0.14.0-dev"
-source = "git+https://github.com/pml68/iced_dialog?branch=iced%2Fpersonal#f751cf15df8533882ee9741701f0997df9529a6f"
+source = "git+https://github.com/pml68/iced_dialog?branch=iced%2Fpersonal#0f4f9283f733e17facca9299c6e8c0060e1e9cd5"
dependencies = [
"iced_core",
"iced_widget",
@@ -2458,6 +2458,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
+name = "iri-string"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2599,9 +2609,9 @@ dependencies = [
[[package]]
name = "libloading"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
+checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.0",
@@ -2665,9 +2675,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
[[package]]
name = "lock_api"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
dependencies = [
"autocfg",
"scopeguard",
@@ -3060,11 +3070,11 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
- "hermit-abi 0.3.9",
+ "hermit-abi",
"libc",
]
@@ -3361,9 +3371,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "openssl"
-version = "0.10.72"
+version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
+checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags 2.9.1",
"cfg-if",
@@ -3393,9 +3403,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
-version = "0.9.108"
+version = "0.9.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
+checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [
"cc",
"libc",
@@ -3472,9 +3482,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -3482,9 +3492,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.10"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
@@ -3591,7 +3601,7 @@ checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
dependencies = [
"cfg-if",
"concurrent-queue",
- "hermit-abi 0.5.1",
+ "hermit-abi",
"pin-project-lite",
"rustix 1.0.7",
"tracing",
@@ -3897,9 +3907,9 @@ dependencies = [
[[package]]
name = "read-fonts"
-version = "0.29.1"
+version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e85935612710191461ec9df47b4b5880dd6359d4fad3b2f2ed696215f6f3146"
+checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d"
dependencies = [
"bytemuck",
"font-types",
@@ -3971,9 +3981,9 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "reqwest"
-version = "0.12.15"
+version = "0.12.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
+checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119"
dependencies = [
"base64",
"bytes",
@@ -3998,21 +4008,20 @@ dependencies = [
"once_cell",
"percent-encoding",
"pin-project-lite",
- "rustls-pemfile",
+ "rustls-pki-types",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
- "system-configuration",
"tokio",
"tokio-native-tls",
"tower",
+ "tower-http",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
- "windows-registry",
]
[[package]]
@@ -4157,15 +4166,6 @@ dependencies = [
]
[[package]]
-name = "rustls-pemfile"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
-dependencies = [
- "rustls-pki-types",
-]
-
-[[package]]
name = "rustls-pki-types"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4340,9 +4340,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.8"
+version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
@@ -4428,9 +4428,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "skrifa"
-version = "0.31.1"
+version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9c3bb8cab5196b98d70c866ce1ea81ab516104d5b396f84ae80f8766b5d5b4e"
+checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607"
dependencies = [
"bytemuck",
"read-fonts",
@@ -4456,9 +4456,9 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.15.0"
+version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "smithay-client-toolkit"
@@ -4507,9 +4507,9 @@ dependencies = [
[[package]]
name = "socket2"
-version = "0.5.9"
+version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -4961,9 +4961,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.8.22"
+version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
@@ -4973,18 +4973,18 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.6.9"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
-version = "0.22.26"
+version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
@@ -4996,9 +4996,9 @@ dependencies = [
[[package]]
name = "toml_write"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "tower"
@@ -5016,6 +5016,24 @@ dependencies = [
]
[[package]]
+name = "tower-http"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
+dependencies = [
+ "bitflags 2.9.1",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "iri-string",
+ "pin-project-lite",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5040,9 +5058,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.28"
+version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
+checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
dependencies = [
"proc-macro2",
"quote",
@@ -5051,9 +5069,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.33"
+version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
+checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [
"once_cell",
]
@@ -5755,13 +5773,13 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
name = "windows-registry"
-version = "0.4.0"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
+checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820"
dependencies = [
+ "windows-link",
"windows-result 0.3.4",
- "windows-strings 0.3.1",
- "windows-targets 0.53.0",
+ "windows-strings 0.4.2",
]
[[package]]
@@ -5794,9 +5812,9 @@ dependencies = [
[[package]]
name = "windows-strings"
-version = "0.3.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link",
]
@@ -6160,6 +6178,16 @@ dependencies = [
]
[[package]]
+name = "winreg"
+version = "0.55.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6541,9 +6569,9 @@ dependencies = [
[[package]]
name = "zune-jpeg"
-version = "0.4.14"
+version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028"
+checksum = "3e4a518c0ea2576f4da876349d7f67a7be489297cd77c2cf9e04c2e05fcd3974"
dependencies = [
"zune-core",
]
diff --git a/src/dialogs.rs b/src/dialogs.rs
index c1933ec..68bbd6e 100644
--- a/src/dialogs.rs
+++ b/src/dialogs.rs
@@ -1,47 +1,103 @@
-use iced::Task;
+use std::borrow::Cow;
+
+use iced::widget::text;
use iced_dialog::button;
use crate::Message;
-use crate::types::{DialogAction, DialogButtons, Element};
+use crate::types::Element;
-pub const UNSAVED_CHANGES_TITLE: &str = "Unsaved changes";
+pub const UNSAVED_CHANGES_TITLE: &str = "Hold on for a sec!";
pub const WARNING_TITLE: &str = "Heads up!";
pub const ERROR_TITLE: &str = "Oops! Something went wrong.";
-pub fn ok_button<'a>() -> Element<'a, Message> {
- button("Ok", Message::DialogOk).into()
+#[derive(Debug, Clone, Copy, Default)]
+pub enum Action {
+ #[default]
+ None,
+ Close,
+ UnsavedChanges(UnsavedChanges),
}
-pub fn cancel_button<'a>() -> Element<'a, Message> {
- button("Cancel", Message::DialogCancel).into()
+#[derive(Debug, Clone, Copy)]
+pub enum UnsavedChanges {
+ New,
+ Open,
+ Exit,
}
-pub fn error_dialog(description: impl Into<String>) -> Task<Message> {
- Task::done(Message::OpenDialog(
- ERROR_TITLE,
- description.into(),
- DialogButtons::Ok,
- DialogAction::None,
- ))
+impl From<Action> for Vec<Element<'_, Message>> {
+ fn from(action: Action) -> Self {
+ match action {
+ Action::None => vec![],
+ Action::Close => vec![button("Close", Message::DialogYes).into()],
+ Action::UnsavedChanges(_) => vec![
+ button("Don't Save", Message::DialogNo).into(),
+ button("Save", Message::DialogYes).into(),
+ button("Cancel", Message::DialogCancel).into(),
+ ],
+ }
+ }
}
-pub fn warning_dialog(description: impl Into<String>) -> Task<Message> {
- Task::done(Message::OpenDialog(
- WARNING_TITLE,
- description.into(),
- DialogButtons::Ok,
- DialogAction::None,
- ))
+#[derive(Debug, Default)]
+pub struct Dialog {
+ is_open: bool,
+ title: Cow<'static, str>,
+ content: Cow<'static, str>,
+ action: Action,
}
-pub fn unsaved_changes_dialog(
- description: impl Into<String>,
- action: DialogAction,
-) -> Task<Message> {
- Task::done(Message::OpenDialog(
- UNSAVED_CHANGES_TITLE,
- description.into(),
- DialogButtons::OkCancel,
- action,
- ))
+impl Dialog {
+ pub fn new(
+ title: impl Into<Cow<'static, str>>,
+ content: impl Into<Cow<'static, str>>,
+ action: Action,
+ ) -> Self {
+ Self {
+ is_open: true,
+ title: title.into(),
+ content: content.into(),
+ action,
+ }
+ }
+
+ pub fn error(content: impl Into<Cow<'static, str>>) -> Self {
+ Self::new(ERROR_TITLE, content, Action::Close)
+ }
+
+ pub fn warning(content: impl Into<Cow<'static, str>>) -> Self {
+ Self::new(WARNING_TITLE, content, Action::Close)
+ }
+
+ pub fn unsaved_changes(
+ content: impl Into<Cow<'static, str>>,
+ unsaved_changes: UnsavedChanges,
+ ) -> Self {
+ Self::new(
+ UNSAVED_CHANGES_TITLE,
+ content,
+ Action::UnsavedChanges(unsaved_changes),
+ )
+ }
+
+ pub fn close(&mut self) {
+ self.is_open = false;
+ }
+
+ pub fn action(&self) -> Action {
+ self.action
+ }
+
+ pub fn as_iced_dialog<'a>(
+ &'a self,
+ base: impl Into<Element<'a, Message>>,
+ ) -> iced_dialog::Dialog<'a, Message, material_theme::Theme> {
+ iced_dialog::Dialog::with_buttons(
+ self.is_open,
+ base,
+ text(&*self.content),
+ self.action.into(),
+ )
+ .title(&*self.title)
+ }
}
diff --git a/src/error.rs b/src/error.rs
index 9e1ee9d..c8405f4 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
use std::io;
use std::sync::Arc;
@@ -57,3 +58,9 @@ impl From<Error> for String {
value.to_string()
}
}
+
+impl From<Error> for Cow<'static, str> {
+ fn from(value: Error) -> Self {
+ value.to_string().into()
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 4d8c351..6be8d5c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,25 +15,18 @@ use std::path::PathBuf;
use std::sync::Arc;
use config::Config;
-use dialogs::{
- cancel_button, error_dialog, ok_button, unsaved_changes_dialog,
- warning_dialog,
-};
+use dialogs::{Action as DialogAction, Dialog, UnsavedChanges};
use error::Error;
use iced::advanced::widget::Id;
-use iced::widget::{
- Column, container, pane_grid, pick_list, row, text, text_editor,
+use iced::widget::{Column, container, pane_grid, pick_list, row, text_editor};
+use iced::{
+ Alignment, Length, Subscription, Task, clipboard, keyboard, window,
};
-use iced::{Alignment, Length, Task, clipboard, keyboard};
use iced_anim::transition::Easing;
use iced_anim::{Animated, Animation};
-use iced_dialog::dialog::Dialog;
use material_theme::Theme;
use panes::{code_view, designer_view, element_list};
-use types::{
- Action, DesignerPane, DialogAction, DialogButtons, Element, Message,
- Project,
-};
+use types::{Action, DesignerPane, Element, Message, Project};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let version = std::env::args()
@@ -54,7 +47,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
)
.title(IcedBuilder::title)
.subscription(IcedBuilder::subscription)
- .theme(|state| state.theme.value().clone())
+ .theme(IcedBuilder::theme)
+ .exit_on_close_request(false)
.font(icon::FONT)
.antialiasing(true)
.centered()
@@ -73,11 +67,7 @@ struct IcedBuilder {
pane_state: pane_grid::State<Panes>,
focus: Option<pane_grid::Pane>,
designer_page: DesignerPane,
- dialog_is_open: bool,
- dialog_title: &'static str,
- dialog_content: String,
- dialog_buttons: DialogButtons,
- dialog_action: DialogAction,
+ dialog: Dialog,
editor_content: text_editor::Content,
}
@@ -112,11 +102,7 @@ impl IcedBuilder {
pane_state: state,
focus: None,
designer_page: DesignerPane::DesignerView,
- dialog_is_open: false,
- dialog_title: "",
- dialog_content: String::new(),
- dialog_buttons: DialogButtons::None,
- dialog_action: DialogAction::None,
+ dialog: Dialog::default(),
editor_content: text_editor::Content::new(),
},
Task::perform(Config::load(), Message::ConfigLoad),
@@ -143,6 +129,10 @@ impl IcedBuilder {
format!("iced Builder{project_name}{saved_state}")
}
+ fn theme(&self) -> Theme {
+ self.theme.value().clone()
+ }
+
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::ConfigLoad(result) => match result {
@@ -151,20 +141,20 @@ impl IcedBuilder {
self.theme.settle_at(self.config.selected_theme());
if let Some(path) = self.config.last_project() {
- return if path.exists() && path.is_file() {
- Task::perform(
+ if path.exists() && path.is_file() {
+ return Task::perform(
Project::from_path(path.to_owned()),
Message::FileOpened,
- )
+ );
} else {
- warning_dialog(format!(
+ self.dialog = Dialog::warning(format!(
"The file {} does not exist, or isn't a file.",
path.to_string_lossy()
- ))
+ ));
};
};
}
- Err(error) => return error_dialog(error),
+ Err(error) => self.dialog = Dialog::error(error),
},
Message::SwitchTheme(event) => self.theme.update(event),
Message::CopyCode => {
@@ -181,7 +171,7 @@ impl IcedBuilder {
self.editor_content =
text_editor::Content::with_text(&code);
}
- Err(error) => return error_dialog(error),
+ Err(error) => self.dialog = Dialog::error(error),
},
Message::DropNewElement(name, point, _) => {
return iced_drop::zones_on_point(
@@ -192,9 +182,6 @@ impl IcedBuilder {
);
}
Message::HandleNew(name, zones) => {
- let refresh_editor_task =
- Task::done(Message::RefreshEditorContent);
-
let ids: Vec<Id> = zones.into_iter().map(|z| z.0).collect();
if !ids.is_empty() {
let action = Action::new(
@@ -212,12 +199,11 @@ impl IcedBuilder {
self.project.element_tree = Some(element.clone());
}
Err(error) => {
- return error_dialog(error)
- .chain(refresh_editor_task);
+ self.dialog = Dialog::error(error);
}
_ => {}
}
- return refresh_editor_task;
+ return self.update(Message::RefreshEditorContent);
}
}
Message::MoveElement(element, point, _) => {
@@ -241,11 +227,11 @@ impl IcedBuilder {
action,
);
if let Err(error) = result {
- return error_dialog(error);
+ self.dialog = Dialog::error(error);
}
self.is_dirty = true;
- return Task::done(Message::RefreshEditorContent);
+ return self.update(Message::RefreshEditorContent);
}
}
Message::PaneResized(pane_grid::ResizeEvent { split, ratio }) => {
@@ -257,37 +243,53 @@ impl IcedBuilder {
target,
}) => self.pane_state.drop(pane, target),
Message::PaneDragged(_) => {}
- Message::OpenDialog(title, content, buttons, action) => {
- self.dialog_title = title;
- self.dialog_content = content;
- self.dialog_buttons = buttons;
- self.dialog_action = action;
- self.dialog_is_open = true;
+ Message::CloseDialog => self.dialog.close(),
+ Message::DialogYes => {
+ return if matches!(
+ self.dialog.action(),
+ DialogAction::UnsavedChanges(_)
+ ) {
+ self.is_loading = true;
+ Task::perform(
+ self.project
+ .clone()
+ .write_to_file(self.project_path.clone()),
+ Message::FileSaved,
+ )
+ .chain(Task::done(Message::DialogNo))
+ } else {
+ self.update(Message::CloseDialog)
+ };
}
- Message::CloseDialog => self.dialog_is_open = false,
- Message::DialogOk => {
- let close_dialog_task = Task::done(Message::CloseDialog);
-
- match self.dialog_action {
- DialogAction::None => {}
- DialogAction::NewFile => {
- self.is_dirty = false;
- self.project = Project::new();
- self.project_path = None;
- self.editor_content = text_editor::Content::new();
- }
- DialogAction::OpenFile => {
- self.is_dirty = false;
- self.is_loading = true;
- return Task::perform(
- Project::from_file(),
- Message::FileOpened,
- )
- .chain(close_dialog_task);
+ Message::DialogNo => {
+ let mut task = Task::done(Message::CloseDialog);
+
+ if let DialogAction::UnsavedChanges(unsaved_changes) =
+ self.dialog.action()
+ {
+ match unsaved_changes {
+ UnsavedChanges::New => {
+ self.is_dirty = false;
+ self.project = Project::new();
+ self.project_path = None;
+ self.editor_content = text_editor::Content::new();
+ }
+ UnsavedChanges::Open => {
+ self.is_dirty = false;
+ self.is_loading = true;
+ task = Task::perform(
+ Project::from_file(),
+ Message::FileOpened,
+ )
+ .chain(task);
+ }
+ UnsavedChanges::Exit => {
+ return self.update(Message::CloseApp);
+ }
}
}
- return close_dialog_task;
+ return task;
}
Message::DialogCancel => return Task::done(Message::CloseDialog),
Message::NewFile => {
@@ -297,9 +299,9 @@ impl IcedBuilder {
self.project_path = None;
self.editor_content = text_editor::Content::new();
} else {
- return unsaved_changes_dialog(
- "You have unsaved changes. Do you wish to discard these and create a new project?",
- DialogAction::NewFile,
+ self.dialog = Dialog::unsaved_changes(
+ "You have unsaved changes. Do you want to save them before creating a new project?",
+ UnsavedChanges::New,
);
}
}
@@ -314,9 +316,9 @@ impl IcedBuilder {
Message::FileOpened,
);
} else {
- return unsaved_changes_dialog(
- "You have unsaved changes. Do you wish to discard these and open another project?",
- DialogAction::OpenFile,
+ self.dialog = Dialog::unsaved_changes(
+ "You have unsaved changes. Do you want to save them before opening another project?",
+ UnsavedChanges::Open,
);
}
}
@@ -325,13 +327,13 @@ impl IcedBuilder {
self.is_loading = false;
self.is_dirty = false;
- return match result {
+ match result {
Ok((path, project)) => {
self.project = project;
self.project_path = Some(path);
- Task::done(Message::RefreshEditorContent)
+ return self.update(Message::RefreshEditorContent);
}
- Err(error) => return error_dialog(error),
+ Err(error) => self.dialog = Dialog::error(error),
};
}
Message::SaveFile => {
@@ -364,16 +366,30 @@ impl IcedBuilder {
self.project_path = Some(path);
self.is_dirty = false;
}
- Err(error) => return error_dialog(error),
+ Err(error) => self.dialog = Dialog::error(error),
+ }
+ }
+ Message::CloseApp => {
+ return window::get_latest().and_then(window::close);
+ }
+ Message::WindowEvent(window::Event::CloseRequested) => {
+ if self.is_dirty {
+ self.dialog = Dialog::unsaved_changes(
+ "You have unsaved changes. Do you want to save them before closing iced Builder?",
+ UnsavedChanges::Exit,
+ );
+ } else {
+ return self.update(Message::CloseApp);
}
}
+ Message::WindowEvent(_) => {}
}
Task::none()
}
fn subscription(&self) -> iced::Subscription<Message> {
- keyboard::on_key_press(|key, modifiers| {
+ let keyboard = keyboard::on_key_press(|key, modifiers| {
if modifiers.command() {
match key.as_ref() {
keyboard::Key::Character("o") => Some(Message::OpenFile),
@@ -390,7 +406,12 @@ impl IcedBuilder {
} else {
None
}
- })
+ });
+
+ let window_events =
+ window::events().map(|(_id, event)| Message::WindowEvent(event));
+
+ Subscription::batch([keyboard, window_events])
}
fn view(&self) -> Element<'_, Message> {
@@ -433,17 +454,9 @@ impl IcedBuilder {
.align_x(Alignment::Center)
.width(Length::Fill);
- let content = Dialog::with_buttons(
- self.dialog_is_open,
- container(base).height(Length::Fill),
- text(&self.dialog_content),
- match self.dialog_buttons {
- DialogButtons::None => vec![],
- DialogButtons::Ok => vec![ok_button()],
- DialogButtons::OkCancel => vec![ok_button(), cancel_button()],
- },
- )
- .title(self.dialog_title);
+ let content = self
+ .dialog
+ .as_iced_dialog(container(base).height(Length::Fill));
Animation::new(&self.theme, content)
.on_update(Message::SwitchTheme)
diff --git a/src/types.rs b/src/types.rs
index 608f285..ef6d5c3 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -7,6 +7,7 @@ use std::path::PathBuf;
pub use element_name::ElementName;
use iced::advanced::widget::Id;
use iced::widget::{pane_grid, text_editor};
+use iced::window;
use iced_anim::Event;
use material_theme::Theme;
pub use project::Project;
@@ -33,9 +34,9 @@ pub enum Message {
PaneResized(pane_grid::ResizeEvent),
PaneClicked(pane_grid::Pane),
PaneDragged(pane_grid::DragEvent),
- OpenDialog(&'static str, String, DialogButtons, DialogAction),
CloseDialog,
- DialogOk,
+ DialogYes,
+ DialogNo,
DialogCancel,
NewFile,
OpenFile,
@@ -43,22 +44,8 @@ pub enum Message {
SaveFile,
SaveFileAs,
FileSaved(Result<PathBuf, Error>),
-}
-
-#[derive(Debug, Clone, Copy, Default)]
-pub enum DialogButtons {
- #[default]
- None,
- Ok,
- OkCancel,
-}
-
-#[derive(Debug, Clone, Copy, Default)]
-pub enum DialogAction {
- #[default]
- None,
- NewFile,
- OpenFile,
+ CloseApp,
+ WindowEvent(window::Event),
}
#[derive(Debug, Clone, Copy)]