Beide Recherchen lagen bisher nur auf lokalen Wegwerf-Branches. Die Kurzfassung steht an den Tickets #2 und #3, die Langfassungen sind mit Quellenangaben und einer Trennung zwischen Belegtem und Vermutetem aber das, worauf man zurueckkommt, wenn spaeter jemand fragt, warum unter Windows Local statt Roaming gewaehlt wurde. Damit sind research/ordner-dialog und research/config-ablageort ueberfluessig und koennen geloescht werden.
29 KiB
Ablageort für die anwendungsweite Konfiguration
Gitea-Issue: #3 (Part of #1) · Stand der Recherche: 2026-08-27
Umfeld: DioNotes, Rust (edition 2021), Dioxus 0.7.1 mit Default-Feature desktop.
Entwicklung unter Windows 11; Linux wird als Zielplattform mitgedacht, macOS nachrangig.
Alle Aussagen sind als [belegt] (Primärquelle, URL angegeben) oder [Vermutung] (Schlussfolgerung, Erfahrungswert, nicht durch eine Quelle abgedeckt) markiert.
1. Kurzantwort
Für die Liste zuletzt benutzter Workspaces:
Pfad unter Windows (ausgeschrieben):
C:\Users\<Benutzername>\AppData\Local\DioNotes\config\recent-workspaces.json
Pfad unter Linux (ausgeschrieben):
/home/<benutzername>/.local/state/dionotes/recent-workspaces.json
Nein, das ist kein Tippfehler und keine Inkonsistenz: Linux hat für „zuletzt benutzt"-Listen
mit $XDG_STATE_HOME einen eigenen Ort, den Windows und macOS nicht kennen. Die XDG-Spec
nennt „recently used files" wörtlich als Beispiel. Begründung und Beleg in Abschnitt 4.2 —
ein einziger Rust-Ausdruck deckt beide Fälle ab.
Rust-Aufruf, der ihn liefert (Crate directories 6.0.0):
use directories::ProjectDirs;
use std::fs;
use std::path::PathBuf;
fn recent_workspaces_file() -> std::io::Result<PathBuf> {
let dirs = ProjectDirs::from("", "", "DioNotes").ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"Home-Verzeichnis des Benutzers nicht ermittelbar",
)
})?;
// state_dir() existiert nur unter Linux (XDG_STATE_HOME) — genau dort gehört
// eine "zuletzt benutzt"-Liste hin. Windows/macOS liefern None, dort ist
// config_local_dir() der richtige Ort. Siehe Abschnitt 3 und 4.
let dir = dirs.state_dir().unwrap_or_else(|| dirs.config_local_dir());
fs::create_dir_all(dir)?; // muss die App selbst tun, siehe Abschnitt 5
Ok(dir.join("recent-workspaces.json"))
}
Derselbe Aufruf liefert plattformübergreifend:
| Plattform | state_dir().unwrap_or_else(|| config_local_dir()) |
Herkunft |
|---|---|---|
| Windows | C:\Users\<Benutzername>\AppData\Local\DioNotes\config |
config_local_dir() (state_dir() ist None) |
| Linux | $XDG_STATE_HOME/dionotes bzw. ~/.local/state/dionotes |
state_dir() |
| macOS | ~/Library/Application Support/DioNotes |
config_local_dir() (state_dir() ist None) |
Zum Vergleich, falls doch eine echte Einstellung (Theme, Schriftgröße) dazukommt — die gehört
nach config_local_dir() bzw. config_dir():
| Plattform | config_local_dir() |
config_dir() |
|---|---|---|
| Windows | …\AppData\Local\DioNotes\config |
…\AppData\Roaming\DioNotes\config |
| Linux | ~/.config/dionotes |
~/.config/dionotes (identisch) |
| macOS | ~/Library/Application Support/DioNotes |
~/Library/Application Support/DioNotes (identisch) |
[belegt] — empirisch verifiziert: Ein Wegwerf-Crate mit directories = "6" unter Windows 11
ausgeführt liefert für ProjectDirs::from("", "", "DioNotes"):
project_path = "DioNotes"
config_dir = "C:\Users\marvin.dietermann\AppData\Roaming\DioNotes\config"
config_local_dir = "C:\Users\marvin.dietermann\AppData\Local\DioNotes\config"
data_local_dir = "C:\Users\marvin.dietermann\AppData\Local\DioNotes\data"
cache_dir = "C:\Users\marvin.dietermann\AppData\Local\DioNotes\cache"
state_dir = None
chosen (state_dir OR config_local_dir) = "C:\Users\marvin.dietermann\AppData\Local\DioNotes\config"
Die Linux-/macOS-Werte stammen aus dem Quelltext von directories 6.0.0 (nicht auf den
Plattformen selbst ausgeführt) — siehe Abschnitt 4.
2. Welche Crate? (dirs vs. directories)
Die beiden Kandidaten
Beide stammen vom selben Autor, teilen sich die Low-Level-Schicht dirs-sys und sind seit
2025-01-12 gemeinsam auf Version 6.0.0. [belegt] — crates.io-API,
https://crates.io/api/v1/crates/dirs und https://crates.io/api/v1/crates/directories:
| Crate | Version | Release-Datum | Downloads gesamt | Downloads (90 Tage) |
|---|---|---|---|---|
dirs |
6.0.0 | 2025-01-12 | ~307,9 Mio. | ~72,4 Mio. |
directories |
6.0.0 | 2025-01-12 | ~67,1 Mio. | ~11,9 Mio. |
dirs-sys |
0.5.0 | 2025-01-11 | ~319,0 Mio. | ~76,5 Mio. |
Beide sind damit der übliche Weg im Rust-Ökosystem; alles andere ist eine Nische.
Arbeitsteilung [belegt] — README von dirs:
„If your requirements are more complex, e.g. computing cache, config, etc. paths for specific applications or projects, consider using
directoriesinstead."https://codeberg.org/dirs/dirs-rs (README, gespiegelt unter https://raw.githubusercontent.com/soc/dirs-rs/main/README.md)
dirs= flache Funktionen, liefern nur das Basisverzeichnis (dirs::config_dir()→%APPDATA%). Den App-Namen hängt man selbst an.directories=ProjectDirs, rechnet den anwendungsspezifischen Unterpfad plattformgerecht aus (Windows:Organisation\App\config, Linux: kleingeschrieben, macOS: Bundle-ID-Form).
Wartungszustand — die wichtigste Einschränkung
[belegt] Die GitHub-Repos sind archiviert. github.com/dirs-dev/directories-rs zeigt:
„This repository was archived by the owner on Feb 18, 2025. It is now read-only." und verweist
auf https://codeberg.org/dirs/directories-rs.
Quellen: https://github.com/dirs-dev/directories-rs, GitHub-API repos/dirs-dev/directories-rs
(archived: true).
[belegt] Die Codeberg-Repos sind nicht archiviert und sind der aktive Ort.
Codeberg-API repos/dirs/directories-rs: archived=false, updated_at=2026-03-22.
Die Commit-Historie zeigt seit dem Release 6.0.0 aber nur noch Metadaten-Commits:
2026-03-20 Update README.md
2025-08-26 Update README to reflect migration from GitHub to Codeberg
2025-04-29 Update Cargo.toml to reflect migration from GitHub to Codeberg
2025-01-12 Release 6.0.0
Quelle: https://codeberg.org/api/v1/repos/dirs/directories-rs/commits (identisches Bild bei
dirs/dirs-rs).
Interpretation [Vermutung]: Die Crates sind nicht verwaist, aber funktional
fertig — seit über 1,5 Jahren keine Code-Änderung. Für „gib mir einen Pfad" ist das kein
Problem; die Known-Folder-/XDG-Konventionen ändern sich nicht. Ein Risiko entstünde erst, wenn
windows-sys o. ä. eine Breaking-Change-Welle auslöst.
Aktiv entwickelte Alternative
etcetera 0.11.0, veröffentlicht 2025-10-28, MSRV 1.87. [belegt] — crates.io-API,
https://crates.io/crates/etcetera, Repo https://github.com/lunacookies/etcetera.
Bietet explizit wählbare „Strategien" (native vs. XDG-überall).
[Vermutung]: Für DioNotes kein Vorteil — die Extra-Flexibilität wird nicht gebraucht,
und die Verbreitung ist geringer.
Empfehlung
directories 6.0.0. Begründung:
-
Es nimmt einem die plattformspezifische Namensform ab (Windows
DioNotes, Linuxdionotes, macOSDioNotesals Bundle-ID-Fragment) — genau die Sorte Detail, die man sonst falsch macht. -
[belegt]
dirs6.0.0 ist bereits transitiv im Dependency-Graph des Projekts:Cargo.locklistetdirs 6.0.0unddirs-sys 0.5.0, hereingezogen überwryundtray-icon(beide überdioxus-desktop). Quelle:Cargo.lockim Repo, Einträgename = "dirs"(Z. 2915) sowie die Dependency-Listen vontray-iconundwry.directorieshat als einzige Nicht-Dev-Dependencydirs-sys ^0.5.0(https://crates.io/api/v1/crates/directories/6.0.0/dependencies) — das Hinzufügen kostet also genau eine zusätzlich kompilierte Crate. -
[belegt] Das offizielle Dioxus-SDK verwendet für seinen Storage selbst
directories:directories::BaseDirs::new().unwrap().data_local_dir().to_path_buf()https://github.com/DioxusLabs/sdk/blob/main/packages/storage/src/client_storage/fs.rs
-
[belegt] Es liefert
state_dir(), das unter Linux auf$XDG_STATE_HOMEzeigt und auf Windows/macOSNoneist — siehe Abschnitt 4.2.dirshat unter Windows zwar auch einstate_dir()(das dortNoneliefert), aber ohneProjectDirsmuss man den App-Namen und dessen plattformspezifische Schreibweise wieder selbst zusammenbauen.
Mit dirs::config_local_dir() käme man unter Windows genauso weit — dann aber ohne
config-Unterordner, ohne den XDG-State-Pfad und ohne die Linux-Kleinschreibung: Man
erzeugte ~/.config/DioNotes statt ~/.config/dionotes. Da Linux ausdrücklich mitgedacht werden
soll, fällt dirs allein damit aus.
3. Welcher Pfad ist der richtige — und unter Windows: Roaming oder Local?
Was die Crate zurückgibt
[belegt] — Quelltext directories 6.0.0, src/win.rs (aus dem lokalen
Cargo-Registry-Checkout, entspricht https://codeberg.org/dirs/directories-rs):
let config_dir = app_data_roaming.join("config");
let config_local_dir = app_data_local.join("config");
let data_dir = app_data_roaming.join("data");
Und dirs 6.0.0, src/win.rs:
pub fn cache_dir() -> Option<PathBuf> { data_local_dir() }
pub fn config_dir() -> Option<PathBuf> { dirs_sys::known_folder_roaming_app_data() }
pub fn config_local_dir() -> Option<PathBuf> { dirs_sys::known_folder_local_app_data() }
pub fn data_dir() -> Option<PathBuf> { dirs_sys::known_folder_roaming_app_data() }
pub fn data_local_dir() -> Option<PathBuf> { dirs_sys::known_folder_local_app_data() }
pub fn preference_dir() -> Option<PathBuf> { dirs_sys::known_folder_local_app_data() }
⚠️ Fallstrick: Die README-Tabelle von
dirsführtpreference_dirunter Windows als{FOLDERID_RoamingAppData}. Der Quelltext und die Laufzeitausgabe sagen LocalAppData. [belegt] durch beides (Quelltext oben; Testlauf liefertedirs::preference_dir() = Some("C:\Users\...\AppData\Local")). Im Zweifel gilt der Code.preference_dirist ohnehin nur auf macOS ein eigener Ort und dort nicht zu benutzen (siehe unten).
Nicht der richtige Pfad ist also:
cache_dir()— löschbar, darf jederzeit verschwinden.data_dir()/data_local_dir()— für Nutzdaten der App, nicht für Einstellungen.preference_dir()— auf macOS~/Library/Preferences, und dort darf man laut Apple gar nicht selbst hineinschreiben (siehe Abschnitt 4).
Richtig ist config_dir() oder config_local_dir().
Roaming vs. Local — die Windows-Konvention
[belegt] Beide Known Folders, Default-Pfade laut Microsoft (https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid):
| KNOWNFOLDERID | GUID | Display Name | Default Path | CSIDL |
|---|---|---|---|---|
FOLDERID_RoamingAppData |
{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D} |
Roaming | %APPDATA% (%USERPROFILE%\AppData\Roaming) |
CSIDL_APPDATA |
FOLDERID_LocalAppData |
{F1B32785-6FBA-4FCF-9D55-7B8E7F157091} |
Local | %LOCALAPPDATA% (%USERPROFILE%\AppData\Local) |
CSIDL_LOCAL_APPDATA |
[belegt] Die Bedeutung, wörtlich aus dem Microsoft-Deployment-Guide (https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766489(v=ws.10)):
„Windows uses the Local and LocalLow folders for application data that does not roam with the user. Usually this data is either machine specific or too large to roam."
„Windows uses the Roaming folder for application specific data, such as custom dictionaries, which are machine independent and should roam with the user profile."
[belegt] Dieselbe Unterscheidung, aktuell gepflegt, in der .NET-API-Doku
(https://learn.microsoft.com/en-us/dotnet/api/system.environment.specialfolder, ms.date 2025-07,
zuletzt aktualisiert 2026-05):
ApplicationData— „The directory that serves as a common repository for application-specific data for the current roaming user. A roaming user works on more than one computer on a network. A roaming user's profile is kept on a server on the network and is loaded onto a system when the user logs on."
LocalApplicationData— „The directory that serves as a common repository for application-specific data that is used by the current, non-roaming user."
[belegt] Und die alte CSIDL-Doku (https://learn.microsoft.com/en-us/windows/win32/shell/csidl):
CSIDL_LOCAL_APPDATA— „The file system directory that serves as a data repository for local (nonroaming) applications."
Das Entscheidungskriterium — und die Anwendung auf DioNotes
Die Konvention fragt nicht „Konfiguration oder Daten?", sondern „maschinenunabhängig oder maschinenspezifisch?":
- maschinenunabhängig (Theme, Schriftgröße, Tastaturkürzel, benutzerdefiniertes Wörterbuch)
→
%APPDATA%(Roaming) →config_dir() - maschinenspezifisch oder groß (absolute Dateipfade, Fensterpositionen, Fenstergrößen,
Caches, Indizes) →
%LOCALAPPDATA%(Local) →config_local_dir()
Die Liste zuletzt benutzter Workspaces besteht aus absoluten Dateisystempfaden. Ein
D:\Notizen\Privat existiert auf dem Laptop im Homeoffice schlicht nicht. Sie ist damit
per Definition maschinenspezifisch und gehört nach %LOCALAPPDATA%.
Das ist eine direkte Anwendung des oben zitierten Microsoft-Satzes — [belegt] in der
Prämisse, [Vermutung] nur insofern, als Microsoft DioNotes nicht namentlich erwähnt.
Empfehlung [Vermutung, gut begründet]: Vorerst alles nach config_local_dir() legen —
also %LOCALAPPDATA%\DioNotes\config\. Gründe:
- Der einzige heute existierende Konfigurationsinhalt (die Workspace-Liste) ist eindeutig maschinenspezifisch.
- Roaming hat reale Fehlermodi, die man sich ohne Not einhandelt: Der Roaming-Ordner wird bei Domänen-Profilen erst beim Ab-/Anmelden synchronisiert, wodurch bei paralleler Nutzung zweier Rechner die letzte Abmeldung gewinnt und Änderungen der anderen Sitzung überschreibt. (Mechanik des Roaming User Profile: https://learn.microsoft.com/en-us/windows-server/storage/folder-redirection/deploy-roaming-user-profiles)
- Zwei Verzeichnisse für eine Handvoll Einstellungen sind Overhead. Ein zweiter Ort
(
config_dir()→%APPDATA%\DioNotes\config\) lohnt sich erst, wenn eine echte maschinenunabhängige Einstellung existiert, die roamen soll.
Wichtig für die Portabilität: Diese Roaming-/Local-Entscheidung ist rein Windows-spezifisch
und kostet auf den anderen Plattformen nichts. [belegt] — Quelltext directories 6.0.0:
unter Linux ist config_local_dir = config_dir.clone() (src/lin.rs), unter macOS ebenso
(src/mac.rs). config_local_dir() zu wählen verbaut also unter Linux/macOS keine Option;
es ist dort schlicht derselbe Pfad.
4. Linux und macOS
Ursprünglich als Nebenfrage angelegt — Linux hat sich beim Nachrecherchieren aber als der Fall herausgestellt, der die Empfehlung tatsächlich verändert. Siehe 4.2.
4.1 Wohin ProjectDirs zeigt
[belegt] Quelltext directories 6.0.0:
src/lin.rs:
pub fn project_dirs_from(_qualifier: &str, _organization: &str, application: &str) -> Option<ProjectDirs> {
ProjectDirs::from_path(PathBuf::from(&trim_and_lowercase_then_replace_spaces(application, "")))
}
// config_dir = $XDG_CONFIG_HOME (sonst $HOME/.config) + project_path
// config_local_dir = config_dir.clone() ← unter Linux identisch!
src/mac.rs:
pub fn project_dirs_from(qualifier: &str, organization: &str, application: &str) -> Option<ProjectDirs> {
let organization = organization.replace(" ", "-");
let application = application.replace(" ", "-");
let mut parts = vec![qualifier, &organization, &application]; parts.retain(|e| !e.is_empty());
let bundle_id = parts.join(".");
ProjectDirs::from_path(PathBuf::from(bundle_id))
}
// config_dir = $HOME/Library/Application Support + project_path
// preference_dir = $HOME/Library/Preferences + project_path
Daraus folgt für ProjectDirs::from("", "", "DioNotes"):
- Linux:
~/.config/dionotes—config_dir()undconfig_local_dir()sind dort dasselbe. Die Roaming-Frage stellt sich unter Linux nicht. - macOS:
~/Library/Application Support/DioNotes(leerer Qualifier/Organisation werden aus der Bundle-ID herausgefiltert).
[belegt] Die Linux-Zuordnung deckt sich mit der XDG Base Directory Specification (https://specifications.freedesktop.org/basedir/latest/):
„
$XDG_CONFIG_HOMEdefines the base directory relative to which user-specific configuration files should be stored. If$XDG_CONFIG_HOMEis either not set or empty, a default equal to$HOME/.config should be used."
[belegt] Für macOS ist Application Support — nicht Preferences — korrekt. Apple, File
System Programming Guide
(https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html):
Library/Application Support— „Use this directory to store all app data files except those associated with the user's documents. For example, you might use this directory to store app-created data files, configuration files, templates … All content in this directory should be placed in a custom subdirectory whose name is that of your app's bundle identifier or your company."
Library/Preferences— „This directory contains app-specific preference files. You should not create files in this directory yourself. Instead, use theNSUserDefaultsclass or CFPreferences API…"
Das ist der Grund, preference_dir() nicht zu benutzen: Es zeigt auf macOS genau in den
Ordner, in den man laut Apple nicht selbst schreiben soll.
4.2 Linux kennt einen dritten Ort — und der ist für unseren Fall der richtige
XDG hat neben config und data noch $XDG_STATE_HOME. [belegt] — XDG Base Directory
Specification Version 0.8 (08. Mai 2021), https://specifications.freedesktop.org/basedir/latest/:
„
$XDG_STATE_HOMEdefines the base directory relative to which user-specific state files should be stored. If$XDG_STATE_HOMEis either not set or empty, a default equal to$HOME/.local/state should be used."
Und zum Inhalt, wörtlich:
„The
$XDG_STATE_HOMEcontains state data that should persist between (application) restarts, but that is not important or portable enough to the user that it should be stored in$XDG_DATA_HOME. It may contain:
- actions history (logs, history, recently used files, …)
- current state of the application that can be reused on a restart (view, layout, open files, undo history, …)"
Das ist keine Auslegung — die Spezifikation nennt „recently used files" und „open files"
namentlich. Eine Liste zuletzt benutzter Workspaces ist unter Linux genau das: State,
nicht Config. Sie gehört nach ~/.local/state/dionotes, nicht nach ~/.config/dionotes.
[belegt] directories 6.0.0 bildet das ab, und zwar nur dort, wo es existiert:
| Plattform | Quelltext | ProjectDirs::state_dir() |
|---|---|---|
| Linux | src/lin.rs Z. 73/84: $XDG_STATE_HOME bzw. $HOME/.local/state, dann .join(project_path), state_dir: Some(state_dir) |
Some("~/.local/state/dionotes") |
| Windows | src/win.rs Z. 89: state_dir: None |
None |
| macOS | src/mac.rs Z. 83: state_dir: None |
None |
Empirisch auf Windows 11 bestätigt: state_dir() = None, und
state_dir().unwrap_or_else(|| config_local_dir()) liefert
C:\Users\…\AppData\Local\DioNotes\config.
Konsequenz für den Aufruf [Vermutung, gut begründet]: Ein einziger Ausdruck ist auf allen drei Plattformen richtig, weil der Fallback genau dann greift, wenn das Betriebssystem den Begriff „State" gar nicht kennt:
let dir = dirs.state_dir().unwrap_or_else(|| dirs.config_local_dir());
Das ist bewusst kein #[cfg(target_os = ...)] — die Fallunterscheidung steckt bereits im
Option, das directories zurückgibt.
4.3 Weitere Linux-Punkte
[belegt] Kleinschreibung wird automatisch erledigt. src/lin.rs reicht den Anwendungsnamen
durch trim_and_lowercase_then_replace_spaces — aus "DioNotes" wird dionotes. Genau das ist
unter Linux üblich; mit dirs (statt directories) müsste man das von Hand tun und würde sonst
ein unschönes ~/.config/DioNotes erzeugen. Das ist das stärkste einzelne Argument für
directories statt dirs.
[belegt] Flatpak/Snap funktionieren ohne Sonderbehandlung. directories liest die
XDG-Variablen zur Laufzeit aus (env::var_os("XDG_CONFIG_HOME"), …("XDG_STATE_HOME"),
jeweils gefiltert durch dirs_sys::is_absolute_path, src/lin.rs Z. 12–19 bzw. 66–73). Eine
Sandbox, die diese Variablen umbiegt (Flatpak setzt sie auf ~/.var/app/<app-id>/…), wird damit
automatisch respektiert.
[Vermutung]: Das eigentliche Sandbox-Problem läge woanders — die in der Liste gespeicherten
absoluten Workspace-Pfade zeigen ggf. aus der Sandbox heraus. Das ist aber eine Frage des
Workspace-Zugriffs, nicht des Ablageorts der Liste.
[belegt] Der HOME-Fallback ist robust. Ist $XDG_STATE_HOME nicht gesetzt oder kein
absoluter Pfad, greift $HOME/.local/state. ProjectDirs::from(...) liefert nur dann None,
wenn sich gar kein Home-Verzeichnis ermitteln lässt — der Fehlerfall ist also derselbe wie unter
Windows und muss ohnehin behandelt werden.
5. Muss die App das Verzeichnis anlegen?
Ja, den anwendungsspezifischen Teil.
[belegt] README von directories und dirs, wörtlich identisch:
„This library does not create directories or check for their existence. The library only provides information on what the path to a certain directory should be."
https://codeberg.org/dirs/directories-rs · https://codeberg.org/dirs/dirs-rs
[belegt] Empirisch auf dem Entwicklungsrechner: Der Testlauf zeigte
"C:\Users\...\AppData\Local\DioNotes" exists = false und
"C:\Users\...\AppData\Roaming\DioNotes" exists = false — ProjectDirs liefert also einen Pfad,
den es nicht gibt.
[belegt] Der Fall ist im Ökosystem üblich: Das Dioxus-SDK ruft direkt nach dem Ermitteln des
Pfads std::fs::create_dir_all(path).unwrap() auf
(https://github.com/DioxusLabs/sdk/blob/main/packages/storage/src/client_storage/fs.rs).
[belegt] Die Basis-Ordner %APPDATA% / %LOCALAPPDATA% selbst existieren dagegen: Sie sind
registrierte Known Folders vom Typ PERUSER und werden mit dem Benutzerprofil angelegt
(https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid). Anzulegen ist also nur
der Teil DioNotes\config.
[belegt] Unter Linux erwartet auch die XDG-Spec, dass die App das tut:
„When attempting to write a file, if the destination directory is non-existent an attempt should be made to create it with permission
0700."
Praktisch: std::fs::create_dir_all(dir)? beim Start bzw. vor dem ersten Schreiben.
create_dir_all ist idempotent und liefert Ok(()), wenn das Verzeichnis schon existiert.
6. Gibt es in Dioxus 0.7 eine eigene Abstraktion dafür?
Nein. Vier unabhängige Belege:
-
[belegt]
dioxus_desktop::Confighat genau zwei Pfad-Methoden —with_resource_directoryundwith_data_directory— und keine davon liefert ein OS-Konfigurationsverzeichnis. https://docs.rs/dioxus-desktop/0.7.1/dioxus_desktop/struct.Config.html -
[belegt]
with_data_directoryist eine Falle. Es klingt richtig, ist aber etwas anderes. Quelltext, Tagv0.7.1(https://github.com/DioxusLabs/dioxus/blob/v0.7.1/packages/desktop/src/config.rs):/// set the directory where data will be stored in release mode. /// /// > Note: This **must** be set when bundling on Windows. pub fn with_data_directory(mut self, path: impl Into<PathBuf>) -> Self { self.data_dir = Some(path.into()); self }Verwendet wird
data_diran genau einer Stelle (https://github.com/DioxusLabs/dioxus/blob/v0.7.1/packages/desktop/src/webview.rs, Z. 262):let mut web_context = WebContext::new(cfg.data_dir.clone());Und
wry::WebContextist das Browser-Profil der WebView:„A context that is shared between multiple WebViews. A browser would have a context for all the normal tabs and a different context for all the private/incognito tabs."
data_directory: „Whether the WebView window should have a custom user data path. This is useful in Windows when a bundled application can't have the webview data inside Program Files."Das ist der Ort für WebView2-Cookies/LocalStorage/Cache, nicht für die Konfiguration der Anwendung.
-
[belegt] Die Item-Liste von
dioxus0.7.1 (https://docs.rs/dioxus/0.7.1/dioxus/all.html) enthält nichts Passendes.dioxus-cli-configbetrifft Build-/Serve-Parameter der CLI,SyncStorage/UnsyncStoragesind Signal-Backends, kein Festplattenspeicher. Zwei unabhängige Doku-Korpora (dioxuslabs.com/learn/0.7als llms-full sowie die Docsite) liefern auf die Frage nach einem Konfigurationsverzeichnis keinen Treffer. Auch die repo-eigeneAGENTS.md(Dioxus-0.7-API-Referenz) enthält dazu nichts. -
[belegt] Das offizielle Dioxus-SDK greift für seinen
use_persistent-Storage selbst zudirectories— wäre in Dioxus etwas eingebaut, hätte es das benutzt. https://github.com/DioxusLabs/sdk/blob/main/packages/storage/src/client_storage/fs.rs
Zu dioxus-sdk / dioxus-storage als Alternative [Vermutung]: Es wäre ebenfalls eine
Extra-Dependency (aktuell auf Dioxus 0.6 ausgerichtet, dioxus-sdk = "0.6"), legt alles nach
BaseDirs::data_local_dir() — also %LOCALAPPDATA% ohne App-Unterordner — und bringt einen
kompletten Hook-Apparat mit. Für eine einzelne JSON-Datei ist das mehr Maschinerie als Nutzen.
7. Offene Punkte / bewusst nicht geklärt
- [nicht geprüft] Verhalten unter Windows, wenn DioNotes als MSIX/Store-App verpackt würde
(dann greift Filesystem-Virtualisierung und
%LOCALAPPDATA%wird umgeleitet). Fürdx bundleals klassische Desktop-App ist das irrelevant. - [nicht geprüft] Die Linux-/macOS-Pfade wurden aus dem Quelltext von
directories6.0.0 abgeleitet und sind dort eindeutig, aber nicht auf den Plattformen selbst ausgeführt. Sobald ein Linux-Build existiert, sollte man den ermittelten Pfad einmal gegenprüfen. - [nicht geprüft] Verhalten unter Flatpak/Snap in der Praxis. Der Mechanismus ist klar (XDG-Variablen werden zur Laufzeit gelesen und damit von der Sandbox respektiert), aber nicht in einer echten Sandbox getestet. Ungeklärt ist dort separat, ob die gespeicherten absoluten Workspace-Pfade aus der Sandbox heraus überhaupt erreichbar sind — eigenes Thema.
- [offen, Folgeentscheidung] Ob
state_dir()auch für spätere echte Einstellungen benutzt wird oder ob dafür ein zweiter Ort (config_local_dir()) aufgemacht wird. Unter Linux wären das zwei getrennte Verzeichnisse (~/.local/state/dionotesund~/.config/dionotes), unter Windows/macOS fielen sie zusammen. Solange es nur die Workspace-Liste gibt, stellt sich die Frage nicht. - [offen, Folgeentscheidung] Dateiformat und Schema der Workspace-Liste (JSON? TOML? Migrationsstrategie bei Formatänderung?) — das ist eine eigene Frage und nicht Teil dieses Tickets.
8. Quellenverzeichnis
Microsoft (Primärquellen für die Windows-Konvention)
- KNOWNFOLDERID: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
- CSIDL: https://learn.microsoft.com/en-us/windows/win32/shell/csidl
Environment.SpecialFolder: https://learn.microsoft.com/en-us/dotnet/api/system.environment.specialfolder- Managing Roaming User Data Deployment Guide: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766489(v=ws.10)
- Deploy roaming user profiles: https://learn.microsoft.com/en-us/windows-server/storage/folder-redirection/deploy-roaming-user-profiles
Plattform-Konventionen Linux / macOS
- XDG Base Directory Specification, Version 0.8 (08.05.2021) —
$XDG_CONFIG_HOME,$XDG_STATE_HOME, Anlegen mit0700: https://specifications.freedesktop.org/basedir/latest/ - Apple, File System Programming Guide: https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
Crates
directories(docs): https://docs.rs/directories/6.0.0/directories/struct.ProjectDirs.htmldirectories(Quelltext, aktiv): https://codeberg.org/dirs/directories-rsdirs(Quelltext, aktiv): https://codeberg.org/dirs/dirs-rs- Archivierte GitHub-Spiegel: https://github.com/dirs-dev/directories-rs, https://github.com/dirs-dev/dirs-rs
- crates.io-Metadaten: https://crates.io/crates/dirs, https://crates.io/crates/directories, https://crates.io/crates/etcetera
Dioxus
dioxus_desktop::Config: https://docs.rs/dioxus-desktop/0.7.1/dioxus_desktop/struct.Config.htmlpackages/desktop/src/config.rs@ v0.7.1: https://github.com/DioxusLabs/dioxus/blob/v0.7.1/packages/desktop/src/config.rspackages/desktop/src/webview.rs@ v0.7.1: https://github.com/DioxusLabs/dioxus/blob/v0.7.1/packages/desktop/src/webview.rswry::WebContext: https://docs.rs/wry/latest/wry/struct.WebContext.html- Dioxus SDK Storage: https://github.com/DioxusLabs/sdk/blob/main/packages/storage/src/client_storage/fs.rs