Files
dionotes-client/docs/research/konfigurations-ablageort.md
MDietermann 8eb0e3325b docs: Rechercheergebnisse zu Ordner-Dialog und Konfigurationsablage uebernehmen
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.
2026-08-27 15:28:28 +02:00

29 KiB
Raw Permalink Blame History

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 directories instead."

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:

  1. Es nimmt einem die plattformspezifische Namensform ab (Windows DioNotes, Linux dionotes, macOS DioNotes als Bundle-ID-Fragment) — genau die Sorte Detail, die man sonst falsch macht.

  2. [belegt] dirs 6.0.0 ist bereits transitiv im Dependency-Graph des Projekts: Cargo.lock listet dirs 6.0.0 und dirs-sys 0.5.0, hereingezogen über wry und tray-icon (beide über dioxus-desktop). Quelle: Cargo.lock im Repo, Einträge name = "dirs" (Z. 2915) sowie die Dependency-Listen von tray-icon und wry. directories hat als einzige Nicht-Dev-Dependency dirs-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.

  3. [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

  4. [belegt] Es liefert state_dir(), das unter Linux auf $XDG_STATE_HOME zeigt und auf Windows/macOS None ist — siehe Abschnitt 4.2. dirs hat unter Windows zwar auch ein state_dir() (das dort None liefert), aber ohne ProjectDirs muss 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 dirs führt preference_dir unter Windows als {FOLDERID_RoamingAppData}. Der Quelltext und die Laufzeitausgabe sagen LocalAppData. [belegt] durch beides (Quelltext oben; Testlauf lieferte dirs::preference_dir() = Some("C:\Users\...\AppData\Local")). Im Zweifel gilt der Code. preference_dir ist 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:

  1. Der einzige heute existierende Konfigurationsinhalt (die Workspace-Liste) ist eindeutig maschinenspezifisch.
  2. 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)
  3. 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() und config_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_HOME defines the base directory relative to which user-specific configuration files should be stored. If $XDG_CONFIG_HOME is 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 the NSUserDefaults class 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_HOME defines the base directory relative to which user-specific state files should be stored. If $XDG_STATE_HOME is either not set or empty, a default equal to $HOME/.local/state should be used."

Und zum Inhalt, wörtlich:

„The $XDG_STATE_HOME contains 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:

  1. [belegt] dioxus_desktop::Config hat genau zwei Pfad-Methoden — with_resource_directory und with_data_directory — und keine davon liefert ein OS-Konfigurationsverzeichnis. https://docs.rs/dioxus-desktop/0.7.1/dioxus_desktop/struct.Config.html

  2. [belegt] with_data_directory ist eine Falle. Es klingt richtig, ist aber etwas anderes. Quelltext, Tag v0.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_dir an 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::WebContext ist 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."

    https://docs.rs/wry/latest/wry/struct.WebContext.html

    Das ist der Ort für WebView2-Cookies/LocalStorage/Cache, nicht für die Konfiguration der Anwendung.

  3. [belegt] Die Item-Liste von dioxus 0.7.1 (https://docs.rs/dioxus/0.7.1/dioxus/all.html) enthält nichts Passendes. dioxus-cli-config betrifft Build-/Serve-Parameter der CLI, SyncStorage/UnsyncStorage sind Signal-Backends, kein Festplattenspeicher. Zwei unabhängige Doku-Korpora (dioxuslabs.com/learn/0.7 als llms-full sowie die Docsite) liefern auf die Frage nach einem Konfigurationsverzeichnis keinen Treffer. Auch die repo-eigene AGENTS.md (Dioxus-0.7-API-Referenz) enthält dazu nichts.

  4. [belegt] Das offizielle Dioxus-SDK greift für seinen use_persistent-Storage selbst zu directories — 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ür dx bundle als klassische Desktop-App ist das irrelevant.
  • [nicht geprüft] Die Linux-/macOS-Pfade wurden aus dem Quelltext von directories 6.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/dionotes und ~/.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)

Plattform-Konventionen Linux / macOS

Crates

Dioxus