Niddy.Core 1.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package Niddy.Core --version 1.0.2
                    
NuGet\Install-Package Niddy.Core -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Niddy.Core" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Niddy.Core" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Niddy.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Niddy.Core --version 1.0.2
                    
#r "nuget: Niddy.Core, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Niddy.Core@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Niddy.Core&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Niddy.Core&version=1.0.2
                    
Install as a Cake Tool

<p align="center"> <img src="https://raw.githubusercontent.com/vonderborch/Niddy/main/assets/branding/niddy-package-icon.png" alt="Niddy logo" width="160" height="160" /> </p>

Niddy

This is my personal utility library. It's public in case it's useful to someone, but it's built for my own projects first: APIs may change between versions, and issues or PRs may not get a response. Use it, fork it, or borrow from it freely (MIT).

A collection of general-purpose .NET utilities and Avalonia UI helpers, split into focused NuGet packages so you only pull in what you need.

Packages

Package What's in it NuGet
Niddy.Core Helpers, threading primitives, and platform-native secure storage; no UI dependencies NuGet
Niddy.Avalonia Avalonia UI dialogs, pages, toasts, theming, file pickers NuGet
Niddy.Avalonia.Generators Optional source generator that registers [PageRegistration] pages automatically; brings in Niddy.Avalonia NuGet
dotnet add package Niddy.Core
dotnet add package Niddy.Avalonia
dotnet add package Niddy.Avalonia.Generators   # optional: automatic page registration

Alternatively, clone this repo and reference the relevant project(s) directly.

Features

Niddy.Core

  • Helpers (Niddy.Helpers): byte manipulation, disposing utilities, IO/path/stream/URL helpers, JSON helpers, list extensions, string extensions, and retry-with-exponential-backoff (sync and async)
  • Threading (Niddy.Threading): lock-free Guard (atomic boolean flag) and AtomicOperations, plus Debouncer and Throttler for bursty events (sync or async actions, TimeProvider-driven, posting back to the captured synchronization context)
  • Results (Niddy.Results): Result, Result<T> and Option<T> value types with Match/Map/Bind, Result.Try/TryAsync and an Error record
  • Humanize (Niddy.Helpers): file sizes (1.5 MB), counts (12.3K), durations (5 min 3 s), relative times (3 minutes ago), plurals and ordinals
  • Files (Niddy.IO): AtomicFile writes (temp file + replace, so a crash never leaves half a file), DebouncedFileWatcher (one batched Changed event per burst), and AppPaths for per-platform data, config, cache and log folders
  • Logging (Niddy.Logging): a rolling file logger for Microsoft.Extensions.Logging (AddFile, NiddyLogging.CreateFactory)
  • Settings (Niddy.Settings): SettingsStore<T>, a typed JSON settings file with atomic saves, Update/Reset, and optional reload on external changes
  • Secure storage (Niddy.Security): platform-native secure storage via ISecureStorage — macOS Keychain, Windows Credential Manager, Linux Secret Service, with an encrypted-file fallback; SecureStorageFactory auto-selects the right implementation

Niddy.Avalonia

  • App setup (Niddy.Avalonia.Hosting): derive your App from NiddyApp and configure pages, dialogs, toasts, theme and the main window in one Configure method. It decides between desktop and mobile mode itself (or you set Mode) and builds the right shell, so you only write pages, never windows
  • Dialog system (Niddy.Avalonia.Dialogs): Dialog static facade for Notification, Confirmation, Warning, Input, MultiInput, Progress, Selection, Exception, Color, Markdown, Table and Web dialogs. Each dialog is one control, shown either as an overlay card or in a modal window (DialogDisplayMode.Auto picks); derive from DialogBase<TResult> and call Dialog.Show for your own dialogs. Every dialog inherits the same title, description and button-row layout from DialogLayout. Window dialogs take an optional fixed windowWidth and windowHeight. Escape, the window close button, and the platform back request act as the cancel button
  • Page system (Niddy.Avalonia.PageSystem): derive pages from Page or Page<TAppDataContext, TPageDataContext>, register them explicitly or automatically with the generator (including pages in referenced projects and plugin assemblies loaded at runtime), and show them in a PageView with a back stack, parameters, lifecycle hooks, navigation guards, kept-alive pages, nested child views and page transitions. Pages can declare keyboard shortcuts (Shortcut = "Primary+1")
  • Data contexts (Niddy.Avalonia.DataContexts): DataContextBase, a ReactiveUI base class for a view's data context with IsBusy/ErrorMessage and a RunAsync helper
  • Toasts: Toast.Show over a ToastHost, shown at any of eight screen positions (ScreenPlacement), with a separate placement for mobile and narrow windows. Toasts can carry an action button (Undo, Retry…), repeated toasts merge into one with a count, and Toast.ShowProgress shows a progress toast you update and complete
  • File pickers: FilePicker returns IStorageFile/IStorageFolder handles, with desktop-only *Path variants
  • Window and layout memory (Niddy.Avalonia.State): windows reopen at their last size, position and state (kept on screen if a monitor went away), and Grid/ProportionalStackPanel splitters keep their sizes, via WindowMemory.Key/LayoutMemory.Key attached properties
  • Global exception handler (Niddy.Avalonia.Hosting): logs UI-thread, unobserved-task and background-thread exceptions and shows Dialog.Exception instead of crashing
  • Converters and markup (Niddy.Avalonia.Converters): enum-to-bool (radio buttons), bool-to-value, humanize and collection-emptiness converters, {niddy:EnumValues}, and one niddy XAML namespace for everything
  • Responsive layout (Niddy.Avalonia.Layout): Responsive.NarrowBelow/WideAbove add narrow/medium/wide classes by width for styles to target

Desktop, mobile, and browser

Everything works on desktop. For mobile and browser apps (a single view, no windows):

  • With NiddyApp this is already set up. Otherwise, wrap your main view's content in a DialogOverlayHost (and a ToastHost for toasts). Dialogs then open as overlays, including Dialog.Exception; without a host, dialogs throw a clear InvalidOperationException because there's no window to open.
  • Use the FilePicker methods that return storage handles; the *Path variants return null there.
  • The platform back request (Android back button, browser back) dismisses an open overlay dialog first, then goes back a page in the most recently attached PageView. Set HandleBackRequests="False" on a PageView to opt out.
  • Overlay dialogs and toasts stay clear of safe-area insets (notch, status and navigation bars) and the on-screen keyboard.

Documentation

Full docs live in docs/: a page per class, with examples, organized by package and folder.

Quick start

An Avalonia app is an App class deriving from NiddyApp, plus pages:

using Niddy.Avalonia.Hosting;
using Niddy.Avalonia.PageSystem;

public class App : NiddyApp
{
    protected override void Configure(NiddyAppOptions options)
    {
        options.Title = "My App";
        options.StartingPage = HomePage.PageId;
        options.AppDataContext = new MainDataContext();
        options.Layout = pages => new PageMenu { Content = pages };   // optional navigation menu
    }
}

// Registered at compile time by Niddy.Avalonia.Generators
[PageRegistration(DisplayName = "Home", Shortcut = "Primary+1")]
public partial class HomePage : Page<MainDataContext, HomePageDataContext>
{
    public HomePage() => InitializeComponent();
}

// Program.cs (desktop)
AppBuilder.Configure<App>().UsePlatformDetect().StartWithClassicDesktopLifetime(args);

Then, from any page:

using Niddy.Avalonia.Dialogs;
using Niddy.Avalonia.Toast;

if (await Dialog.Warning.Open(this, "Delete project?", "This can't be undone.", yesButtonText: "Delete"))
{
    DeleteProject();
    Toast.Show(this, "Project deleted", actionText: "Undo", action: RestoreProject);
}

NavigateTo<SettingsPage>();

And Niddy.Core, in any app:

using Niddy.IO;
using Niddy.Logging;
using Niddy.Security;

var paths = AppPaths.For("MyApp").EnsureCreated();                 // per-platform data, config, cache, log folders
using var loggerFactory = NiddyLogging.CreateFactory(paths);         // rolling log files in paths.Logs
ISecureStorage secrets = SecureStorageFactory.Create(paths.Data, "MyApp");   // keychain / credential manager
secrets.SetToken("api-key", key);

See the docs for everything else.

Development

Requires the .NET 10 SDK (pinned in global.json).

The packages live under src/, and each has a test project under tests/ (xUnit v3; the Avalonia tests run headless, and the generator tests run the generator on in-memory compilations). tests/Fixtures/ holds small page libraries the tests reference or load at runtime. Run them all with dotnet test.

  1. Clone or fork the repo
  2. Create a new branch
  3. Code!
  4. Push your changes and open a PR
  5. Once approved, they'll be merged in
  6. Profit!

Releasing

All packages share one SemVer 2 version, taken from the GitHub release tag.

  1. Create a GitHub release with a tag like v1.2.0 (or v1.3.0-beta.1 for a pre-release; the leading v is optional)
  2. Publishing the release runs the publish workflow, which runs the tests, then packs every project at that version and pushes it to NuGet

Publishing uses nuget.org trusted publishing, so no API key is stored in the repo. It needs, once:

  • a trusted publishing policy on nuget.org (your username → Trusted Publishing) for owner vonderborch, repository Niddy and workflow file nuget-publish.yml
  • a NUGET_USER repository secret holding the nuget.org profile name that owns the packages

Local builds are versioned 0.0.0-dev.

Future Plans

See list of issues under the Milestones: https://github.com/vonderborch/Niddy/milestones

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Niddy.Core:

Package Downloads
Niddy.Avalonia

Niddy: my personal .NET utilities. Avalonia UI helpers: app hosting, dialogs (window and overlay, including color, markdown, table and web), a page system with menus and keyboard shortcuts, toasts with actions and progress, window and layout memory, a global exception handler, converters, responsive layout, theming and file pickers.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 109 10/11/2026
1.1.2 107 10/9/2026
1.1.1 101 10/8/2026
1.0.2 113 9/27/2026
1.0.1 122 9/27/2026