diff --git a/Cargo.lock b/Cargo.lock index c615b8cb..cb09fabb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -230,6 +230,28 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbc3a507a82b17ba0d98f6ce8fd6954ea0c8152e98009d36a40d8dcc8ce078a" +[[package]] +name = "ashpd" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.2", + "raw-window-handle", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + [[package]] name = "askar-crypto" version = "0.3.7" @@ -325,6 +347,18 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-channel" version = "2.5.0" @@ -350,6 +384,49 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.1", +] + [[package]] name = "async-lock" version = "3.4.1" @@ -361,12 +438,52 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + [[package]] name = "async-once-cell" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "async-rx" version = "0.1.3" @@ -377,6 +494,24 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.1", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -399,6 +534,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.89" @@ -668,6 +809,19 @@ dependencies = [ "objc2", ] +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bls12_381" version = "0.8.0" @@ -714,6 +868,12 @@ version = "1.5.0" 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.11.1" @@ -1429,7 +1589,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.1", ] [[package]] @@ -1439,6 +1599,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", + "block2", + "libc", "objc2", ] @@ -1571,6 +1733,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1584,7 +1773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -2529,6 +2718,21 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png 0.18.0", + "zune-core 0.5.1", + "zune-jpeg", +] + [[package]] name = "imagesize" version = "0.12.0" @@ -2814,7 +3018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.4", ] [[package]] @@ -3010,7 +3214,7 @@ dependencies = [ "makepad-platform", "makepad-rustybuzz", "makepad-vector", - "png", + "png 0.17.16", "sdfer", "serde", "ttf-parser", @@ -3306,7 +3510,7 @@ name = "makepad-zune-png" version = "0.4.10" source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "zune-core", + "zune-core 0.4.12", "zune-inflate", ] @@ -3697,6 +3901,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -3709,6 +3922,16 @@ version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbf6f36070878c42c5233846cd3de24cf9016828fd47bc22957a687298bb21fc" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3736,6 +3959,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "moxcms" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "multihash" version = "0.19.3" @@ -3941,6 +4174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.10.0", + "block2", "objc2", "objc2-foundation", ] @@ -4069,6 +4303,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "p256" version = "0.13.2" @@ -4244,6 +4488,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -4284,6 +4539,39 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "png" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +dependencies = [ + "bitflags 2.10.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.1", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + [[package]] name = "poly1305" version = "0.8.0" @@ -4448,6 +4736,15 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" +[[package]] +name = "pxfm" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" +dependencies = [ + "num-traits", +] + [[package]] name = "quick-xml" version = "0.37.5" @@ -4602,6 +4899,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "readlock" version = "0.1.9" @@ -4758,6 +5061,30 @@ dependencies = [ "subtle", ] +[[package]] +name = "rfd" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" +dependencies = [ + "ashpd", + "block2", + "dispatch2", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "pollster", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.59.0", +] + [[package]] name = "rgb" version = "0.8.52" @@ -4883,6 +5210,7 @@ dependencies = [ "futures-util", "hashbrown 0.16.1", "htmlize", + "image", "imbl", "imghdr", "indexmap 2.13.0", @@ -4892,11 +5220,13 @@ dependencies = [ "matrix-sdk", "matrix-sdk-base", "matrix-sdk-ui", + "mime_guess", "percent-encoding", "quinn", "rand 0.8.5", "rangemap", "reqwest", + "rfd", "robius-directories", "robius-location", "robius-open", @@ -5146,7 +5476,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -5477,6 +5807,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "serde_spanned" version = "1.0.3" @@ -5993,7 +6334,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -6098,7 +6439,7 @@ dependencies = [ "bytemuck", "cfg-if", "log", - "png", + "png 0.17.16", "tiny-skia-path", ] @@ -6476,6 +6817,17 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "ulid" version = "1.2.1" @@ -6968,15 +7320,37 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39b7d07a236abaef6607536ccfaf19b396dbe3f5110ddb73d39f4562902ed382" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.1", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.56.0" @@ -7524,6 +7898,67 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfeff997a0aaa3eb20c4652baf788d2dfa6d2839a0ead0b3ff69ce2f9c4bdd1" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.1", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bbd5a90dbe8feee5b13def448427ae314ccd26a49cac47905cafefb9ff846f1" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.106", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.8.27" @@ -7630,6 +8065,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -7638,3 +8079,53 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[package]] +name = "zune-jpeg" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410e9ecef634c709e3831c2cfdb8d9c32164fae1c67496d5b68fff728eec37fe" +dependencies = [ + "zune-core 0.5.1", +] + +[[package]] +name = "zvariant" +version = "5.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b64ef4f40c7951337ddc7023dd03528a57a3ce3408ee9da5e948bd29b232c4" +dependencies = [ + "endi", + "enumflags2", + "serde", + "url", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484d5d975eb7afb52cc6b929c13d3719a20ad650fea4120e6310de3fc55e415c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.106", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.106", + "winnow", +] diff --git a/Cargo.toml b/Cargo.toml index 5c041614..48886ff8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,10 +44,12 @@ hashbrown = { version = "0.16", features = ["raw-entry"] } htmlize = "1.0.5" indexmap = "2.6.0" imghdr = "0.7.0" +image = { version = "0.25", default-features = false, features = ["jpeg", "png"] } linkify = "0.10.0" matrix-sdk-base = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main" } matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ "e2e-encryption", "automatic-room-key-forwarding", "markdown", "sqlite", "rustls-tls", "bundled-sqlite", "sso-login" ] } matrix-sdk-ui = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ "rustls-tls" ] } +mime_guess = "2.0.5" ## Use the same ruma version as what's specified in matrix-sdk's Cargo.toml. ## Enable a few extra features: ## * "compat-optional" feature to allow missing body field in m.room.tombstone event. @@ -64,7 +66,7 @@ tokio = { version = "1.43.1", features = ["macros", "rt-multi-thread"] } tracing-subscriber = "0.3.17" unicode-segmentation = "1.11.0" url = "2.5.0" - +rfd = { version = "0.15.3", features = ["ashpd", "urlencoding", "xdg-portal"] } ## Dependencies for TSP support. ## Commit "f0bc4625dcd729e07e4a36257df2f1d94c81cef4" is the most recent one without the invalid change to pin serde to 1.0.219. diff --git a/resources/icons/add_attachment.svg b/resources/icons/add_attachment.svg new file mode 100644 index 00000000..e378316d --- /dev/null +++ b/resources/icons/add_attachment.svg @@ -0,0 +1,17 @@ + + + + + attachment + Created with Sketch Beta. + + + + + + + + + + + \ No newline at end of file diff --git a/resources/icons/file.svg b/resources/icons/file.svg new file mode 100644 index 00000000..3a249469 --- /dev/null +++ b/resources/icons/file.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index d3ea88bd..046bc8a1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -14,7 +14,7 @@ use crate::{ }, login::login_screen::LoginAction, logout::logout_confirm_modal::{LogoutAction, LogoutConfirmModalAction, LogoutConfirmModalWidgetRefExt}, persistence, profile::user_profile_cache::clear_user_profile_cache, room::BasicRoomDetails, shared::{callout_tooltip::{ CalloutTooltipWidgetRefExt, TooltipAction, - }, confirmation_modal::{ConfirmationModalContent, ConfirmationModalWidgetRefExt}, image_viewer::{ImageViewerAction, LoadState}, popup_list::{PopupKind, enqueue_popup_notification}}, sliding_sync::{DirectMessageRoomAction, MatrixRequest, current_user_id, submit_async_request}, utils::RoomNameId, verification::VerificationAction, verification_modal::{ + }, confirmation_modal::{ConfirmationModalContent, ConfirmationModalWidgetRefExt}, file_upload_modal::FilePreviewerAction, image_viewer::{ImageViewerAction, LoadState}, popup_list::{PopupKind, enqueue_popup_notification}}, sliding_sync::{DirectMessageRoomAction, MatrixRequest, current_user_id, submit_async_request}, utils::RoomNameId, verification::VerificationAction, verification_modal::{ VerificationModalAction, VerificationModalWidgetRefExt, } @@ -39,6 +39,7 @@ live_design! { use crate::home::event_source_modal::EventSourceModal; use crate::shared::callout_tooltip::CalloutTooltip; use crate::shared::image_viewer::ImageViewer; + use crate::shared::file_upload_modal::FileUploadModal; use link::tsp_link::TspVerificationModal; @@ -101,6 +102,13 @@ live_design! { image_viewer_modal_inner = {} } } + file_upload_modal = { + content: { + height: Fill, width: Fill, + align: {x: 0.5, y: 0.5}, + file_upload_modal_inner = {} + } + } // Context menus should be shown in front of other UI elements, // but behind verification modals. @@ -508,6 +516,17 @@ impl MatchEvent for App { } _ => {} } + match action.downcast_ref() { + Some(FilePreviewerAction::Show(_)) => { + self.ui.modal(ids!(file_upload_modal)).open(cx); + continue; + } + Some(FilePreviewerAction::Hide) => { + self.ui.modal(ids!(file_upload_modal)).close(cx); + continue; + } + _ => {} + } // Handle actions to open/close the TSP verification modal. #[cfg(feature = "tsp")] { use std::ops::Deref; diff --git a/src/home/mod.rs b/src/home/mod.rs index 8f8ea8e9..4e6eabad 100644 --- a/src/home/mod.rs +++ b/src/home/mod.rs @@ -29,6 +29,8 @@ pub mod new_message_context_menu; pub mod room_context_menu; pub mod link_preview; pub mod room_image_viewer; +pub mod thumbnail_loading; +pub mod upload_progress; pub fn live_design(cx: &mut Cx) { search_messages::live_design(cx); @@ -59,4 +61,6 @@ pub fn live_design(cx: &mut Cx) { light_themed_dock::live_design(cx); event_reaction_list::live_design(cx); link_preview::live_design(cx); + thumbnail_loading::live_design(cx); + upload_progress::live_design(cx); } diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 35205143..3cd64840 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -957,6 +957,7 @@ impl Widget for RoomScreen { timeline_kind: tl.kind.clone(), room_members, room_avatar_url, + timeline_update_sender: Some(tl.update_sender.clone()), } } else if let Some(room_name) = &self.room_name_id { // Fallback case: we have a room_name but no tl_state yet @@ -967,6 +968,7 @@ impl Widget for RoomScreen { .expect("BUG: room_name_id was set but timeline_kind was missing"), room_members: None, room_avatar_url: None, + timeline_update_sender: None, } } else { // No room selected yet, skip event handling that requires room context @@ -982,6 +984,7 @@ impl Widget for RoomScreen { timeline_kind: TimelineKind::MainRoom { room_id }, room_members: None, room_avatar_url: None, + timeline_update_sender: None, } }; let mut room_scope = Scope::with_props(&room_props); @@ -1617,6 +1620,32 @@ impl RoomScreen { tl.tombstone_info = Some(successor_room_details); } TimelineUpdate::LinkPreviewFetched => {} + TimelineUpdate::FileUploadConfirmed(file_data) => { + // Handle file upload confirmation from the file upload modal. + // This ensures the upload is associated with the correct timeline. + let room_input_bar = self.view.room_input_bar(ids!(room_input_bar)); + if let Some(replied_to) = room_input_bar.handle_file_upload_confirmed(cx) { + submit_async_request(MatrixRequest::SendAttachment { + timeline_kind: tl.kind.clone(), + file_data, + replied_to, + #[cfg(feature = "tsp")] + sign_with_tsp: room_input_bar.is_tsp_signing_enabled(cx), + }); + } + } + TimelineUpdate::FileUploadUpdate { current, total } => { + let room_input_bar = self.view.room_input_bar(ids!(room_input_bar)); + room_input_bar.set_progress_value(cx, current, total); + } + TimelineUpdate::FileUploadAbortHandle(handle) => { + let room_input_bar = self.view.room_input_bar(ids!(room_input_bar)); + room_input_bar.set_abort_handle(handle); + } + TimelineUpdate::FileUploadError { error, file_data } => { + let room_input_bar = self.view.room_input_bar(ids!(room_input_bar)); + room_input_bar.handle_upload_error(cx, error, file_data); + } } } @@ -2274,6 +2303,7 @@ impl RoomScreen { content_drawn_since_last_update: RangeSet::new(), profile_drawn_since_last_update: RangeSet::new(), update_receiver, + update_sender: update_sender.clone(), request_sender, media_cache: MediaCache::new(Some(update_sender.clone())), link_preview_cache: LinkPreviewCache::new(Some(update_sender)), @@ -2631,6 +2661,10 @@ pub struct RoomScreenProps { pub timeline_kind: TimelineKind, pub room_members: Option>>, pub room_avatar_url: Option, + /// The sender for timeline updates, used for operations like file uploads + /// that need to notify this specific timeline. + /// This is `None` in fallback cases where the timeline state isn't fully loaded yet. + pub timeline_update_sender: Option>, } @@ -2759,6 +2793,25 @@ pub enum TimelineUpdate { Tombstoned(SuccessorRoomDetails), /// A notice that link preview data for a URL has been fetched and is now available. LinkPreviewFetched, + /// A file upload was confirmed from the file upload modal. + FileUploadConfirmed(crate::shared::file_upload_modal::FileData), + /// An update on the progress of a file upload that is currently in-flight. + FileUploadUpdate { + /// Current progress value (e.g., bytes uploaded). + current: u64, + /// Total value to reach (e.g., total file size in bytes). + total: u64, + }, + /// A file upload failed with an error. + /// Includes the file data so the user can retry the upload. + FileUploadError { + /// The error message describing why the upload failed. + error: String, + /// The file data that can be used to retry the upload. + file_data: crate::shared::file_upload_modal::FileData, + }, + /// A notice that a file upload in this timeline was aborted. + FileUploadAbortHandle(tokio::task::AbortHandle), } thread_local! { @@ -2820,6 +2873,10 @@ struct TimelineUiState { /// which is okay because a sender on an unbounded channel never needs to block. update_receiver: crossbeam_channel::Receiver, + /// The channel sender for timeline updates for this room. + /// This is passed to child widgets that need to send updates to this timeline. + update_sender: crossbeam_channel::Sender, + /// The sender for timeline requests from a RoomScreen showing this room /// to the background async task that handles this room's timeline updates. request_sender: TimelineRequestSender, diff --git a/src/home/thumbnail_loading.rs b/src/home/thumbnail_loading.rs new file mode 100644 index 00000000..7caaef80 --- /dev/null +++ b/src/home/thumbnail_loading.rs @@ -0,0 +1,40 @@ +//! A simple loading view displayed while generating thumbnails for file uploads. + +use makepad_widgets::*; + +live_design! { + use link::theme::*; + use link::shaders::*; + use link::widgets::*; + use crate::shared::styles::*; + + // A view that displays a loading spinner and text while generating thumbnails. + pub ThumbnailLoadingView = { + visible: false, + width: Fill, + height: Fit, + padding: {top: 8, bottom: 8, left: 10, right: 10} + flow: Right, + spacing: 10, + align: {y: 0.5} + + loading_spinner = { + width: 25, + height: 25, + draw_bg: { + color: (COLOR_ACTIVE_PRIMARY) + border_size: 3.0, + } + } + + loading_text =