commit 6a989e388b7609ba71dddbc3b8da5945450d78b4
parent 21c00a41e0b6b62db22327c89cee7c06dbab5057
Author: William Casarin <jb55@jb55.com>
Date: Mon, 2 Sep 2024 17:56:18 -0700
Merge images support
Thanks to Ken Sedgwick for getting this over the line by generalizing
our images cache!
Ken Sedgwick (2):
build: updated num_enum to get around build problem
Extend ImageCache to handle content images
William Casarin (4):
update image to 0.25
initial image support
use slightly better carousel id
Fixes: https://github.com/damus-io/notedeck/issues/249
Fixes: https://github.com/damus-io/notedeck/issues/148
Diffstat:
7 files changed, 524 insertions(+), 98 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -77,6 +77,12 @@ dependencies = [
]
[[package]]
+name = "aligned-vec"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
+
+[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -117,7 +123,7 @@ dependencies = [
"ndk 0.8.0",
"ndk-context",
"ndk-sys 0.5.0+25.2.9519653",
- "num_enum 0.7.2",
+ "num_enum 0.7.3",
"thiserror",
]
@@ -210,6 +216,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
+name = "arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
+
+[[package]]
name = "arboard"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -225,6 +237,17 @@ dependencies = [
]
[[package]]
+name = "arg_enum_proc_macro"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
name = "arrayref"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -286,6 +309,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
+name = "av1-grain"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf"
+dependencies = [
+ "anyhow",
+ "arrayvec",
+ "log",
+ "nom",
+ "num-rational",
+ "v_frame",
+]
+
+[[package]]
+name = "avif-serialize"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2"
+dependencies = [
+ "arrayvec",
+]
+
+[[package]]
name = "backtrace"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -454,6 +500,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
+name = "bitstream-io"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "415f8399438eb5e4b2f73ed3152a3448b98149dda642a957ee704e1daa5cf1d8"
+
+[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -506,6 +558,12 @@ dependencies = [
]
[[package]]
+name = "built"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6a6c0b39c38fd754ac338b00a88066436389c0f029da5d37d1e01091d9b7c17"
+
+[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -538,6 +596,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
+name = "byteorder-lite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
+
+[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -605,6 +669,16 @@ dependencies = [
]
[[package]]
+name = "cfg-expr"
+version = "0.15.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
+dependencies = [
+ "smallvec",
+ "target-lexicon",
+]
+
+[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -936,7 +1010,7 @@ dependencies = [
"egui-wgpu",
"egui-winit",
"egui_glow",
- "image 0.25.1",
+ "image",
"js-sys",
"log",
"objc2 0.5.2",
@@ -1015,7 +1089,7 @@ dependencies = [
"egui",
"ehttp 0.5.0",
"enum-map",
- "image 0.25.1",
+ "image",
"log",
"mime_guess2",
"resvg",
@@ -1799,34 +1873,35 @@ dependencies = [
[[package]]
name = "image"
-version = "0.24.9"
+version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
+checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"exr",
"gif",
- "jpeg-decoder",
+ "image-webp",
"num-traits",
"png",
"qoi",
+ "ravif",
+ "rayon",
+ "rgb",
"tiff",
+ "zune-core",
+ "zune-jpeg",
]
[[package]]
-name = "image"
-version = "0.25.1"
+name = "image-webp"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11"
+checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d"
dependencies = [
- "bytemuck",
- "byteorder",
- "color_quant",
- "gif",
- "num-traits",
- "png",
+ "byteorder-lite",
+ "thiserror",
]
[[package]]
@@ -1836,6 +1911,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
[[package]]
+name = "imgref"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126"
+
+[[package]]
name = "indexmap"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1869,6 +1950,17 @@ dependencies = [
]
[[package]]
+name = "interpolate_name"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
name = "ipnet"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1942,9 +2034,6 @@ name = "jpeg-decoder"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
-dependencies = [
- "rayon",
-]
[[package]]
name = "js-sys"
@@ -2006,6 +2095,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
+name = "libfuzzer-sys"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
+dependencies = [
+ "arbitrary",
+ "cc",
+ "once_cell",
+]
+
+[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2065,6 +2165,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
+name = "loop9"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
+dependencies = [
+ "imgref",
+]
+
+[[package]]
name = "lz4_flex"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2080,6 +2189,16 @@ dependencies = [
]
[[package]]
+name = "maybe-rayon"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
+dependencies = [
+ "cfg-if",
+ "rayon",
+]
+
+[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2212,7 +2331,7 @@ dependencies = [
"jni-sys",
"log",
"ndk-sys 0.5.0+25.2.9519653",
- "num_enum 0.7.2",
+ "num_enum 0.7.3",
"raw-window-handle 0.6.2",
"thiserror",
]
@@ -2248,6 +2367,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe"
[[package]]
+name = "new_debug_unreachable"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
+
+[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2264,6 +2389,12 @@ dependencies = [
]
[[package]]
+name = "noop_proc_macro"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
+
+[[package]]
name = "nostr"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2326,7 +2457,7 @@ dependencies = [
"enostr",
"env_logger 0.10.2",
"hex",
- "image 0.24.9",
+ "image",
"log",
"nostrdb",
"poll-promise",
@@ -2359,12 +2490,53 @@ dependencies = [
]
[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
+name = "num-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
+dependencies = [
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2403,11 +2575,11 @@ dependencies = [
[[package]]
name = "num_enum"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845"
+checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
dependencies = [
- "num_enum_derive 0.7.2",
+ "num_enum_derive 0.7.3",
]
[[package]]
@@ -2416,7 +2588,7 @@ version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
dependencies = [
- "proc-macro-crate 1.3.1",
+ "proc-macro-crate",
"proc-macro2",
"quote",
"syn 1.0.109",
@@ -2428,7 +2600,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
dependencies = [
- "proc-macro-crate 1.3.1",
+ "proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.68",
@@ -2436,11 +2608,11 @@ dependencies = [
[[package]]
name = "num_enum_derive"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
+checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
- "proc-macro-crate 3.1.0",
+ "proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.68",
@@ -2816,15 +2988,6 @@ dependencies = [
]
[[package]]
-name = "proc-macro-crate"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
-dependencies = [
- "toml_edit 0.21.1",
-]
-
-[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2838,6 +3001,19 @@ name = "profiling"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
+dependencies = [
+ "profiling-procmacros",
+]
+
+[[package]]
+name = "profiling-procmacros"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
+dependencies = [
+ "quote",
+ "syn 2.0.68",
+]
[[package]]
name = "puffin"
@@ -2882,6 +3058,12 @@ dependencies = [
]
[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
name = "quick-xml"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2977,6 +3159,56 @@ dependencies = [
]
[[package]]
+name = "rav1e"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9"
+dependencies = [
+ "arbitrary",
+ "arg_enum_proc_macro",
+ "arrayvec",
+ "av1-grain",
+ "bitstream-io",
+ "built",
+ "cfg-if",
+ "interpolate_name",
+ "itertools",
+ "libc",
+ "libfuzzer-sys",
+ "log",
+ "maybe-rayon",
+ "new_debug_unreachable",
+ "noop_proc_macro",
+ "num-derive",
+ "num-traits",
+ "once_cell",
+ "paste",
+ "profiling",
+ "rand",
+ "rand_chacha",
+ "simd_helpers",
+ "system-deps",
+ "thiserror",
+ "v_frame",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "ravif"
+version = "0.11.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67376f469e7e7840d0040bbf4b9b3334005bb167f814621326e4c7ab8cd6e944"
+dependencies = [
+ "avif-serialize",
+ "imgref",
+ "loop9",
+ "quick-error",
+ "rav1e",
+ "rayon",
+ "rgb",
+]
+
+[[package]]
name = "raw-window-handle"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3462,6 +3694,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3517,6 +3758,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
+name = "simd_helpers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
+dependencies = [
+ "quote",
+]
+
+[[package]]
name = "simplecss"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3713,6 +3963,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]]
+name = "system-deps"
+version = "6.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
+dependencies = [
+ "cfg-expr",
+ "heck",
+ "pkg-config",
+ "toml",
+ "version-compare",
+]
+
+[[package]]
+name = "target-lexicon"
+version = "0.12.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
+
+[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3913,10 +4182,25 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit 0.22.14",
+]
+
+[[package]]
name = "toml_datetime"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
+dependencies = [
+ "serde",
+]
[[package]]
name = "toml_edit"
@@ -3926,18 +4210,20 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"toml_datetime",
- "winnow",
+ "winnow 0.5.40",
]
[[package]]
name = "toml_edit"
-version = "0.21.1"
+version = "0.22.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
+checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
dependencies = [
"indexmap",
+ "serde",
+ "serde_spanned",
"toml_datetime",
- "winnow",
+ "winnow 0.6.13",
]
[[package]]
@@ -4248,6 +4534,17 @@ dependencies = [
]
[[package]]
+name = "v_frame"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b"
+dependencies = [
+ "aligned-vec",
+ "num-traits",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4260,6 +4557,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322"
[[package]]
+name = "version-compare"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
+
+[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4984,6 +5287,15 @@ dependencies = [
]
[[package]]
+name = "winnow"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "winreg"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5089,6 +5401,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
+name = "zune-core"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
+
+[[package]]
name = "zune-inflate"
version = "0.2.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5096,3 +5414,12 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [
"simd-adler32",
]
+
+[[package]]
+name = "zune-jpeg"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448"
+dependencies = [
+ "zune-core",
+]
diff --git a/Cargo.toml b/Cargo.toml
@@ -21,7 +21,7 @@ egui_tabs = { git = "https://github.com/damus-io/egui-tabs", branch = "egui-0.28
egui_nav = { git = "https://github.com/damus-io/egui-nav", branch = "egui-0.28" }
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", branch = "egui-0.28", package = "egui_virtual_list" }
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
-image = { version = "0.24", features = ["jpeg", "png", "webp"] }
+image = { version = "0.25", features = ["jpeg", "png", "webp"] }
log = "0.4.17"
poll-promise = { version = "0.3.0", features = ["tokio"] }
serde_derive = "1"
diff --git a/src/images.rs b/src/images.rs
@@ -102,54 +102,72 @@ pub fn round_image(image: &mut ColorImage) {
}
}
-fn process_pfp_bitmap(size: u32, image: &mut image::DynamicImage) -> ColorImage {
+fn process_pfp_bitmap(imgtyp: ImageType, image: &mut image::DynamicImage) -> ColorImage {
#[cfg(feature = "profiling")]
puffin::profile_function!();
- // Crop square
- let smaller = image.width().min(image.height());
-
- if image.width() > smaller {
- let excess = image.width() - smaller;
- *image = image.crop_imm(excess / 2, 0, image.width() - excess, image.height());
- } else if image.height() > smaller {
- let excess = image.height() - smaller;
- *image = image.crop_imm(0, excess / 2, image.width(), image.height() - excess);
+ match imgtyp {
+ ImageType::Content(w, h) => {
+ let image = image.resize(w, h, FilterType::CatmullRom); // DynamicImage
+ let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer)
+ let color_image = ColorImage::from_rgba_unmultiplied(
+ [
+ image_buffer.width() as usize,
+ image_buffer.height() as usize,
+ ],
+ image_buffer.as_flat_samples().as_slice(),
+ );
+ color_image
+ }
+ ImageType::Profile(size) => {
+ // Crop square
+ let smaller = image.width().min(image.height());
+
+ if image.width() > smaller {
+ let excess = image.width() - smaller;
+ *image = image.crop_imm(excess / 2, 0, image.width() - excess, image.height());
+ } else if image.height() > smaller {
+ let excess = image.height() - smaller;
+ *image = image.crop_imm(0, excess / 2, image.width(), image.height() - excess);
+ }
+ let image = image.resize(size, size, FilterType::CatmullRom); // DynamicImage
+ let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer)
+ let mut color_image = ColorImage::from_rgba_unmultiplied(
+ [
+ image_buffer.width() as usize,
+ image_buffer.height() as usize,
+ ],
+ image_buffer.as_flat_samples().as_slice(),
+ );
+ round_image(&mut color_image);
+ color_image
+ }
}
- let image = image.resize(size, size, FilterType::CatmullRom); // DynamicImage
- let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer)
- let mut color_image = ColorImage::from_rgba_unmultiplied(
- [
- image_buffer.width() as usize,
- image_buffer.height() as usize,
- ],
- image_buffer.as_flat_samples().as_slice(),
- );
- round_image(&mut color_image);
- color_image
}
-fn parse_img_response(response: ehttp::Response, size: u32) -> Result<ColorImage> {
+fn parse_img_response(response: ehttp::Response, imgtyp: ImageType) -> Result<ColorImage> {
#[cfg(feature = "profiling")]
puffin::profile_function!();
let content_type = response.content_type().unwrap_or_default();
+ let size_hint = match imgtyp {
+ ImageType::Profile(size) => SizeHint::Size(size, size),
+ ImageType::Content(w, h) => SizeHint::Size(w, h),
+ };
if content_type.starts_with("image/svg") {
#[cfg(feature = "profiling")]
puffin::profile_scope!("load_svg");
- let mut color_image = egui_extras::image::load_svg_bytes_with_size(
- &response.bytes,
- Some(SizeHint::Size(size, size)),
- )?;
+ let mut color_image =
+ egui_extras::image::load_svg_bytes_with_size(&response.bytes, Some(size_hint))?;
round_image(&mut color_image);
Ok(color_image)
} else if content_type.starts_with("image/") {
#[cfg(feature = "profiling")]
puffin::profile_scope!("load_from_memory");
let mut dyn_image = image::load_from_memory(&response.bytes)?;
- Ok(process_pfp_bitmap(size, &mut dyn_image))
+ Ok(process_pfp_bitmap(imgtyp, &mut dyn_image))
} else {
Err(format!("Expected image, found content-type {:?}", content_type).into())
}
@@ -181,11 +199,20 @@ fn fetch_img_from_disk(
})
}
+/// Controls type-specific handling
+#[derive(Debug, Clone, Copy)]
+pub enum ImageType {
+ /// Profile Image (size)
+ Profile(u32),
+ /// Content Image (width, height)
+ Content(u32, u32),
+}
+
pub fn fetch_img(
img_cache: &ImageCache,
ctx: &egui::Context,
url: &str,
- size: u32,
+ imgtyp: ImageType,
) -> Promise<Result<TextureHandle>> {
let key = ImageCache::key(url);
let path = img_cache.cache_dir.join(key);
@@ -193,7 +220,7 @@ pub fn fetch_img(
if path.exists() {
fetch_img_from_disk(ctx, url, &path)
} else {
- fetch_img_from_net(&img_cache.cache_dir, ctx, url, size)
+ fetch_img_from_net(&img_cache.cache_dir, ctx, url, imgtyp)
}
// TODO: fetch image from local cache
@@ -203,7 +230,7 @@ fn fetch_img_from_net(
cache_path: &path::Path,
ctx: &egui::Context,
url: &str,
- size: u32,
+ imgtyp: ImageType,
) -> Promise<Result<TextureHandle>> {
let (sender, promise) = Promise::new();
let request = ehttp::Request::get(url);
@@ -213,7 +240,7 @@ fn fetch_img_from_net(
ehttp::fetch(request, move |response| {
let handle = response
.map_err(Error::Generic)
- .and_then(|resp| parse_img_response(resp, size))
+ .and_then(|resp| parse_img_response(resp, imgtyp))
.map(|img| {
let texture_handle = ctx.load_texture(&cloned_url, img.clone(), Default::default());
diff --git a/src/imgcache.rs b/src/imgcache.rs
@@ -42,7 +42,7 @@ impl ImageCache {
data.as_raw(),
data.size[0] as u32,
data.size[1] as u32,
- image::ColorType::Rgba8,
+ image::ColorType::Rgba8.into(),
)?;
Ok(())
diff --git a/src/timeline.rs b/src/timeline.rs
@@ -202,6 +202,7 @@ impl TimelineTab {
let selection = 0i32;
let mut list = VirtualList::new();
list.hide_on_resize(None);
+ list.over_scan(1000.0);
let list = Rc::new(RefCell::new(list));
let notes: Vec<NoteRef> = Vec::with_capacity(cap);
@@ -344,7 +345,6 @@ impl Timeline {
}
}
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MergeKind {
FrontInsert,
Spliced,
diff --git a/src/ui/note/contents.rs b/src/ui/note/contents.rs
@@ -1,4 +1,7 @@
+use crate::images::ImageType;
+use crate::imgcache::ImageCache;
use crate::ui::note::NoteOptions;
+use crate::ui::ProfilePic;
use crate::{colors, ui, Damus};
use egui::{Color32, Hyperlink, Image, RichText};
use nostrdb::{BlockType, Mention, Note, NoteKey, Transaction};
@@ -111,7 +114,7 @@ fn render_note_contents(
puffin::profile_function!();
let selectable = options.has_selectable_text();
- let images: Vec<String> = vec![];
+ let mut images: Vec<String> = vec![];
let mut inline_note: Option<(&[u8; 32], &str)> = None;
let resp = ui.horizontal_wrapped(|ui| {
@@ -156,19 +159,17 @@ fn render_note_contents(
}
BlockType::Url => {
- /*
- let url = block.as_str().to_lowercase();
- if url.ends_with("png") || url.ends_with("jpg") {
- images.push(url);
+ let lower_url = block.as_str().to_lowercase();
+ if lower_url.ends_with("png") || lower_url.ends_with("jpg") {
+ images.push(block.as_str().to_string());
} else {
- */
- #[cfg(feature = "profiling")]
- puffin::profile_scope!("url contents");
- ui.add(Hyperlink::from_label_and_url(
- RichText::new(block.as_str()).color(colors::PURPLE),
- block.as_str(),
- ));
- //}
+ #[cfg(feature = "profiling")]
+ puffin::profile_scope!("url contents");
+ ui.add(Hyperlink::from_label_and_url(
+ RichText::new(block.as_str()).color(colors::PURPLE),
+ block.as_str(),
+ ));
+ }
}
BlockType::Text => {
@@ -188,15 +189,85 @@ fn render_note_contents(
render_note_preview(ui, damus, txn, id, block_str);
}
- for image in images {
- let img_resp = ui.add(Image::new(image.clone()));
- img_resp.context_menu(|ui| {
- if ui.button("Copy Link").clicked() {
- ui.ctx().copy_text(image);
- ui.close_menu();
- }
- });
+ if !images.is_empty() && !damus.textmode {
+ ui.add_space(2.0);
+ let carousel_id = egui::Id::new(("carousel", note.key().expect("expected tx note")));
+ image_carousel(ui, &mut damus.img_cache, images, carousel_id);
+ ui.add_space(2.0);
}
resp
}
+
+fn image_carousel(
+ ui: &mut egui::Ui,
+ img_cache: &mut ImageCache,
+ images: Vec<String>,
+ carousel_id: egui::Id,
+) {
+ // let's make sure everything is within our area
+
+ let height = 360.0;
+ let width = ui.available_size().x;
+ let spinsz = if height > width { width } else { height };
+
+ ui.add_sized([width, height], |ui: &mut egui::Ui| {
+ egui::ScrollArea::horizontal()
+ .id_source(carousel_id)
+ .show(ui, |ui| {
+ ui.horizontal(|ui| {
+ for image in images {
+ // If the cache is empty, initiate the fetch
+ let m_cached_promise = img_cache.map().get(&image);
+ if m_cached_promise.is_none() {
+ let res = crate::images::fetch_img(
+ img_cache,
+ ui.ctx(),
+ &image,
+ ImageType::Content(width.round() as u32, height.round() as u32),
+ );
+ img_cache.map_mut().insert(image.to_owned(), res);
+ }
+
+ // What is the state of the fetch?
+ match img_cache.map()[&image].ready() {
+ // Still waiting
+ None => {
+ ui.add(egui::Spinner::new().size(spinsz));
+ }
+ // Failed to fetch image!
+ Some(Err(_err)) => {
+ // FIXME - use content-specific error instead
+ let no_pfp = crate::images::fetch_img(
+ img_cache,
+ ui.ctx(),
+ ProfilePic::no_pfp_url(),
+ ImageType::Profile(128),
+ );
+ img_cache.map_mut().insert(image.to_owned(), no_pfp);
+ // spin until next pass
+ ui.add(egui::Spinner::new().size(spinsz));
+ }
+ // Use the previously resolved image
+ Some(Ok(img)) => {
+ let img_resp = ui.add(
+ Image::new(img)
+ .max_height(height)
+ .rounding(5.0)
+ .fit_to_original_size(1.0),
+ );
+ img_resp.context_menu(|ui| {
+ if ui.button("Copy Link").clicked() {
+ ui.ctx().copy_text(image);
+ ui.close_menu();
+ }
+ });
+ }
+ }
+ }
+ })
+ .response
+ })
+ .inner
+ });
+}
diff --git a/src/ui/profile/picture.rs b/src/ui/profile/picture.rs
@@ -1,3 +1,4 @@
+use crate::images::ImageType;
use crate::imgcache::ImageCache;
use crate::ui::{Preview, PreviewConfig, View};
use egui::{vec2, Sense, TextureHandle};
@@ -72,7 +73,7 @@ fn render_pfp(
let m_cached_promise = img_cache.map().get(url);
if m_cached_promise.is_none() {
- let res = crate::images::fetch_img(img_cache, ui.ctx(), url, img_size);
+ let res = crate::images::fetch_img(img_cache, ui.ctx(), url, ImageType::Profile(img_size));
img_cache.map_mut().insert(url.to_owned(), res);
}
@@ -87,7 +88,7 @@ fn render_pfp(
img_cache,
ui.ctx(),
ProfilePic::no_pfp_url(),
- img_size,
+ ImageType::Profile(img_size),
);
img_cache.map_mut().insert(url.to_owned(), no_pfp);
}