Nativer Ordner-Dialog unter Dioxus 0.7 Desktop #2
Notifications
Due Date
No due date set.
Blocks
#6 Fehlerfälle beim Anlegen und Öffnen
RDietermann/dionotes-client
#8 Selector-UI: Anlegen und Öffnen
RDietermann/dionotes-client
Reference: RDietermann/dionotes-client#2
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #1
Question
Mit welcher Bibliothek öffnet eine Dioxus-0.7-Desktop-App den nativen Ordner-Auswahldialog des Betriebssystems, und wie sieht der Aufruf konkret aus?
Konkret zu klären:
rfd? etwas aus dem Dioxus-SDK? etwas Webview-eigenes?) und ist sie mit Dioxus 0.7 / dessen Webview-Version kompatibel?onclick?Zielgröße: eine benennbare Crate mit Version, ein lauffähiges Beispiel-Snippet für „Ordner wählen", und die Aussage, ob das unter Windows out of the box läuft.
Antwort
Crate:
rfd(„Rusty File Dialogs"), aktuell0.17.2(veröffentlicht 2026-01-12). Das ist der Standardweg — und der einzige belastbare.dioxus-sdk 0.7.0hat die Featuresgeolocation, notification, storage, sync, time, util, window— kein Dialog-Modul. (crates.io)Kompatibilität: ja, konfliktfrei
dioxus-desktop 0.7.1ziehttao ^0.34.0undwry ^0.53.5.rfd 0.17.2hängt an keinem davon — die einzige Berührungsfläche istraw-window-handle ^0.6, dastao 0.34per Default-Featurerwh_06ebenfalls bedient. Kein Versionskonflikt.Blockierend oder async: zwingend async
Es gibt beide Varianten:
rfd::FileDialog::pick_folder(self) -> Option<PathBuf>— synchronrfd::AsyncFileDialog::pick_folder(self) -> impl Future<Output = Option<FileHandle>>— asyncDie synchrone fährt die modale COM-Schleife auf dem aufrufenden Thread (
dialog.show()ininit_com). Dioxus-Event-Handler undspawn-Tasks laufen auf dem Main-Thread —pub fn spawn(fut: impl Future<Output = ()> + 'static) -> Taskhat keinSend-Bound, kann den Thread also gar nicht wechseln. EinFileDialog::pick_folder()imonclickfriert die tao-Event-Loop ein.Die async-Variante lagert unter Windows den Dialog auf einen eigenen OS-Thread aus und liefert per Channel zurück (
std::thread::spawn(move || { tx.send(f()).ok(); })inpick_folder_async) — die Event-Loop läuft weiter. Kein Tokio-/async-std-Feature nötig,rfdhat keine Runtime-Dependency.Abbruch
None. KeinResult, keine Fehlerunterscheidung: ein technisch fehlgeschlagener Dialog ist von einem abgebrochenen nicht unterscheidbar (die Windows-Impl endet aufrun(self).ok()).Snippet (Dioxus 0.7 API)
Windows: ja, out of the box
Einzige Windows-Dependency ist
windows-sys ^0.61(FeaturesWin32_Foundation,Win32_System_Com,Win32_UI_Shell*,Win32_UI_WindowsAndMessaging) — reines Rust-Binding, keine C-Header, kein vcpkg, kein Feature-Flag.rfd = "0.17"eintragen, fertig. Das Featurecommon-controls-v6betrifft nur Message-Dialoge, nicht Ordner-Dialoge.macOS / Linux
NSApplication-Instanz" ist in einer tao-App erfüllt.xdg-portalbraucht zur Laufzeitlibdbus(sonst Fallback aufzenity) und ein installiertes Portal-Backend (GTK/GNOME/KDE; wlroots reicht nicht). Alternativedefault-features = false, features = ["gtk3"]braucht GTK3-Dev-Header zur Build-Zeit.Der Rust-Code ist auf allen drei Plattformen identisch — das Packaging unter Linux nicht.
Offen / nicht belegt
set_parent(&*use_window())für einen besitzer-modalen Dialog: typtheoretisch plausibel (DesktopService: Deref<Target = tao::Window>,tao::Window: HasWindowHandleviarwh_06), aber nicht kompiliert. Empfehlung: erst ohneset_parent.Langfassung mit Quellenangabe je Aussage:
docs/research/nativer-ordner-dialog.mdauf Branchresearch/ordner-dialog(lokal, nicht gepusht).Nachtrag / Korrektur zum Kommentar oben
Eine Gegenprüfung hat zwei Dinge zutage gefördert, die den Kommentar oben an einer Stelle falsch machen und an einer zweiten deutlich entschärfen.
1. Korrektur: Dioxus hat sehr wohl einen eigenen Ordner-Dialog-Weg
Oben stand „Dioxus selbst bringt keine Datei-/Ordner-Dialog-API mit". Das ist falsch. Die offizielle 0.7-Doku beschreibt Ordner-Auswahl über ein
directory-Attribut am File-Input:(dioxuslabs.com/learn/0.7/essentials/basics/event_handlers)
Auf dem Desktop ist das kein Browser-Dialog —
dioxus-desktopfeuert dahinter exakt den nativen rfd-Ordner-Dialog:Und der absolute Pfad ist öffentlich abgreifbar:
pub fn path(&self) -> PathBufaufdioxus_html::FileData(docs.rs).Weg A — null neue Dependencies:
Grenze: braucht ein DOM-Element und einen echten Klick darauf. Ein programmatisch geöffneter Dialog (Menü, Shortcut, Wizard-Folgeschritt) geht damit nicht — dafür bleibt Weg B (
rfddirekt) wie oben beschrieben.2. Entschärfung:
rfdist längst im Dependency-GraphCargo.tomlsagtdioxus = "0.7.1", aufgelöst wird real aber 0.7.10 (Cargo.lockZeile 2337/2493). Unddioxus-desktop 0.7.10ziehtrfd ^0.17.2nicht-optional herein (default-features = false, features = ["xdg-portal"], Target-cfg für Windows/macOS/BSDs) — crates.io. Bestätigt durchCargo.lock:rfd 0.17.2,tao 0.34.8,wry 0.53.5.Heißt:
rfd = "0.17"einzutragen fügt dem Graph keinen neuen Crate hinzu und kostet keinen zusätzlichen Compile-Unit. Die Features vereinigt Cargo additiv, unsere Defaults sind ohnehinxdg-portal. Das „ist es die Dependency wert?"-Argument gegen Weg B fällt damit weitgehend weg.(Randnotiz:
dioxus-desktop 0.7.1hatte nochrfd ^0.15.3— der Sprung auf 0.17 kam zwischen 0.7.1 und 0.7.10.)3. Bestätigt geblieben
dioxus-sdk 0.7.0hat kein Dialog-Modul (Features:geolocation, notification, storage, sync, time, util, window).dioxus_desktop::rfdgibt es nicht —mod file_upload;ist privat, die Re-Export-Liste inlib.rsführt nurtao,wry,muda,trayicon,launch,AssetRequest,Config,DesktopContext/DesktopService,WryEventHandler,hooks::*, Shortcut-Typen undwry::RequestAsyncResponder.Noneund „Windows out of the box" im Kommentar oben gilt unverändert.Empfehlung
Reine UX-Frage: Dialog aus einem sichtbaren Button/Input im Workspace-Formular → Weg A. Dialog programmatisch → Weg B. Beide landen unter Windows im selben nativen
IFileOpenDialog.Langfassung aktualisiert:
docs/research/nativer-ordner-dialog.mdauf Branchresearch/ordner-dialog(Commit68c2ae7, lokal, nicht gepusht).