WIP: New drag-and-drop type system#11487
WIP: New drag-and-drop type system#11487eira-fransham wants to merge 26 commits intoslint-ui:feature/drag-and-dropfrom
Conversation
@eira-fransham CI should run on draft PRs 🤔 Did it not? |
Oh! My mistake |
LeonMatthes
left a comment
There was a problem hiding this comment.
This looks like it's going in a good direction, especially reading the data from the clipboard seems to be nice and easy.
The read side could still benefit a lot from optionals, so that you don't have to do two separate calls. But until we have those, this works well.
We will need to discuss the construction side of the clipboard data types in Slint though. Because as we are seeing here, just creating the data from a string and an image is not enough.
E.g. the component MIME type is now using text/plain in our preview UI, which it shouldn't.
We could use a built-in macro function, which could accept any data type as the data argument.
Something like: clipboard-data("application/x-slint-component", "...")
Another side note on this, maybe we should move away from using a property in the drag area, but rather have a callback like get-data so that we can load the data when you start the drag.
|
|
||
| output.write_all( | ||
| b"#![deny(warnings)]\n#![deny(rust_2018_idioms)]\n#![deny(unsafe_code)]\n", | ||
| b"#![warn(rust_2018_idioms)]\n#![deny(unsafe_code)]\n#![allow(clippy::all)]", |
There was a problem hiding this comment.
I assume this is just temporary?
There was a problem hiding this comment.
I do kinda think we should merge something like this to main because deny(warnings) is considered harmful (we should either use a CLI flag on CI and/or explicitly deny each separate thing if we really want to do that), but you're right that I didn't mean to include it in this PR, it was just because clippy warnings were causing my LSP to go haywire
There was a problem hiding this comment.
Denying warnings is indeed harmful in library code that someone else may depend on, but this is our own testing code, where this is fine in my opinion.
Then you also get the same behavior when testing locally as you do in CI.
| (Type::String | Type::Image, Type::ClipboardData) => { | ||
| quote!(sp::ClipboardData::from(#f)) | ||
| } |
There was a problem hiding this comment.
It would be quite convenient if we can cast these types to clipboard data but I don't know if this is expressive enough.
For example, what mime type does the image get? Is it an `"image/png"? Or the string? Is it just "text/plain" or "text/marked-down"?
I'm intrigued by the idea though. Maybe we can make it work. But we need to check whether the mime-type is defaulting to the right thing.
There was a problem hiding this comment.
I think SharedString would be text/plain, and Image would be image/* (i.e. it can provide the image in any format you like). StyledText would be text/markdown, application/rtf (required to make copying styled text work on Windows), etc. We should have some way to read text/markdown as SharedString but I won't include that in this PR for now.
| | Type::LayoutCache | ||
| | Type::ArrayOfU16 => return None, | ||
| | Type::ArrayOfU16 | ||
| | Type::ClipboardData => return None, |
There was a problem hiding this comment.
The ClipboardData will need a default in Slint, otherwise it will blow up if it's used in a struct (see also: #11489 )
There was a problem hiding this comment.
Oh! The default should be the same as for Type::Void, so I added it to this branch. Didn't realise that was how it worked (I'm guessing because void isn't a valid field type).
| } | ||
| } | ||
|
|
||
| /// Private version of [`ClipboardData`] so we can implement the traits that we expect |
There was a problem hiding this comment.
This is actually not the private version, this is the public Slint type.
There was a problem hiding this comment.
Whoops, outdated docs. Thanks for catching it, I made a mental note to fix it and then never did.
| /// | ||
| /// - `text/*`: `SharedString` (this will require boxing the `SharedString` inside an `Rc`) | ||
| pub trait ClipboardData { | ||
| pub trait ClipboardDataProvider { |
There was a problem hiding this comment.
Hm, not a fan of this name, but also don't have a better idea atm, so let's bikeshed the naming.
There was a problem hiding this comment.
It was actually the original name I used for the trait until I decided that Rc<dyn ClipboardData> should be what's passed around. I kinda think that this name makes more sense, since IMO it makes it clearer that it does IO.
There was a problem hiding this comment.
Maybe I missed the discussion here, but did we talk about adding an any-type to Slint?
Honestly, the motivation for this, even with clipboard, is probably not strong enough. Within Slint, you're most likely not going to use any. You're going to boil this down to concrete types.
So we could just stick with dyn Any in the Rust side and use concrete constructors for the clipboard data on the Slint side.
There was a problem hiding this comment.
I'm not adding an any type to Slint, I did try that but didn't like how implicit the interface was. I explain why I didn't want to use dyn Any in the chat (I'll send you a link as a DM since it's in the internal channel), but to sum it up: using dyn Any makes it trivial for implementers of ClipboardDataProvider to accidentally return the wrong type - e.g. String instead of SharedString - and limiting the interface makes that harder to do by accident.
55937ba to
73c8656
Compare
…i#11446) Bumps the npm-patch-updates group with 6 updates: | Package | From | To | | --- | --- | --- | | [@napi-rs/cli](https://github.com/napi-rs/napi-rs) | `3.6.1` | `3.6.2` | | [vite-plugin-singlefile](https://github.com/richardtallent/vite-plugin-singlefile) | `2.3.2` | `2.3.3` | | [@astrojs/partytown](https://github.com/withastro/astro/tree/HEAD/packages/integrations/partytown) | `2.1.6` | `2.1.7` | | [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.11` | `2.4.12` | | [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `6.1.5` | `6.1.8` | | [typescript](https://github.com/microsoft/TypeScript) | `6.0.2` | `6.0.3` | Updates `@napi-rs/cli` from 3.6.1 to 3.6.2 - [Release notes](https://github.com/napi-rs/napi-rs/releases) - [Commits](https://github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.6.1...@napi-rs/cli@3.6.2) Updates `vite-plugin-singlefile` from 2.3.2 to 2.3.3 - [Release notes](https://github.com/richardtallent/vite-plugin-singlefile/releases) - [Changelog](https://github.com/richardtallent/vite-plugin-singlefile/blob/main/CHANGELOG.md) - [Commits](https://github.com/richardtallent/vite-plugin-singlefile/commits) Updates `@astrojs/partytown` from 2.1.6 to 2.1.7 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/integrations/partytown/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/@astrojs/partytown@2.1.7/packages/integrations/partytown) Updates `@biomejs/biome` from 2.4.11 to 2.4.12 - [Release notes](https://github.com/biomejs/biome/releases) - [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md) - [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.12/packages/@biomejs/biome) Updates `astro` from 6.1.5 to 6.1.8 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/astro@6.1.8/packages/astro) Updates `typescript` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](microsoft/TypeScript@v6.0.2...v6.0.3) --- updated-dependencies: - dependency-name: "@napi-rs/cli" dependency-version: 3.6.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-patch-updates - dependency-name: vite-plugin-singlefile dependency-version: 2.3.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-patch-updates - dependency-name: "@astrojs/partytown" dependency-version: 2.1.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-patch-updates - dependency-name: "@biomejs/biome" dependency-version: 2.4.12 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-patch-updates - dependency-name: astro dependency-version: 6.1.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-patch-updates - dependency-name: typescript dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-patch-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Lets AI agents fetch /docs/.../foo.md instead of the HTML page, saving tokens on retrieval. Implemented as a static Astro endpoint over the docs collection, so it works the same on Cloudflare Pages and Netlify with no per-host routing.
The markdown sibling endpoint now resolves the <Link/> component into a real markdown link pointing at the target page's .md sibling, so AI agents can chain markdown fetches without rewriting URLs. Two safety nets keep the output honest: - A Playwright spec asserts no unresolved MDX components leak into any built .md file. - A post-build script walks the .md corpus with remark and verifies every internal link points at an existing file. Wired into the build step so a broken link fails the build.
* refactor: use wgpu re-exported from slint and remove redundant wgpu-hal/wgpu dependencies * refactor: improve lib * docs: Update README for new implementation * refactor: move get_wgpu_texture_from_metal from GPURenderingContext to metal module extension trait * refactor: fix wgpu_hal import to wpgu::hal from slint * hal * refactor: decouple android and linux gpu rendering context configurations to support platform-specific API detection * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Migrate the testing backend introspection handle storage from generational-arena to slotmap. This removes the unmaintained generational-arena dependency from the internal testing backend while keeping the existing handle serialization format used by the MCP and system-testing APIs.
Reject malformed wire handles before they reach slotmap so even generations and oversized parts do not normalize into live keys. This fixes the broken slotmap migration roundtrip test, propagates invalid-handle errors through the MCP and system-testing paths, and adds focused coverage for malformed handle decoding.
73c8656 to
77d3a58
Compare
| cmd.arg("--error-exitcode=1"); | ||
| cmd.arg("--num-callers=50"); | ||
| cmd.arg(binary_path.deref()); | ||
| } else if std::env::var("USE_LLDB").is_ok() { |
There was a problem hiding this comment.
Added as an alternative to valgrind for platforms where it doesn't work, since valgrind can't run on macOS, Windows, or CachyOS (Linux distro with AVX512 enabled for libraries).
…nnecessary docs change
- Rename `ClipboardData`/`clipboard-data` to `DataTransfer`/`data-transfer` - Remove Slint API for `data-transfer`, forcing use of global callbacks - New API for constructing `DataTransfer`, more similar to JS DOM API - Bytes-based API for data
tronical
left a comment
There was a problem hiding this comment.
A first round of review. I'll hold off until you give the signal for further review :). Glad that we've settled on DataTransfer btw :)
| Type::DataTransfer => { | ||
| if let Some(clipboard_data) = unknown | ||
| .coerce_to_object()? | ||
| .get::<ExternalRef<DataTransfer>>("clipboard_data") |
There was a problem hiding this comment.
This should probably be transfer_data for the string literal as well as the variable.
| Type::DataTransfer => Expression::Cast { | ||
| from: Box::new(Expression::CodeBlock(Default::default())), | ||
| to: ty.clone(), | ||
| }, |
There was a problem hiding this comment.
I think it would be cleaner and clearer to have an expression instead of the implicit cast from an empty code block.
| /// Enable support for additional formats supported by the [`image` crate](https://crates.io/crates/image) ( | ||
| /// AVIF, BMP, DDS, Farbfeld, GIF, HDR, ICO, JPEG, EXR, PNG, PNM, QOI, TGA, TIFF, WebP) | ||
| /// by enabling the `image-default-formats` cargo feature. | ||
| pub fn load_from_dynamic_data(bytes: &[u8], format: &str) -> Result<Self, LoadImageError> { |
There was a problem hiding this comment.
I suggest to leave that out from the public API as part of this PR and we do this separately.
| ClipboardTypeNotFound(String), | ||
| } | ||
|
|
||
| impl Clone for PlatformError { |
| } | ||
|
|
||
| impl DataTransfer { | ||
| pub fn set_internal(&mut self, value: Rc<dyn Any>) -> &mut Self { |
There was a problem hiding this comment.
Did you mean set_any here? I think that's the name we discussed and I can see it in the outline page.
(set_internal sounds too much like an internal function)
| self.internal.clone() | ||
| } | ||
|
|
||
| pub fn read_plaintext(&self) -> Result<SharedString, PlatformError> { |
There was a problem hiding this comment.
We had discussed get_ instead of read in the review.
| api::{Image, PlatformError}, | ||
| }; | ||
|
|
||
| pub mod mime; |
There was a problem hiding this comment.
I don't think that's meant to be public API, right? (at least it's not in the outline page we discussed)
| pub use drag_n_drop::*; | ||
| #[cfg(feature = "path")] | ||
| mod path; | ||
| pub use crate::DataTransfer; |
There was a problem hiding this comment.
Since DataTransfer isn't an Item, why does it have to be exported under items?
| } | ||
|
|
||
| /// Try to convert the type to `to`, or return self unmodified as an error. | ||
| pub fn try_cast(self, to: LangType) -> Result<Self, Self> { |
There was a problem hiding this comment.
Given that LangType isn't public, this function should probably also not be public.
Closes #11400
This isn't a draft PR as I want CI to run, but it shouldn't be merged yet.