Files
2026-06-08 02:39:44 +08:00
..
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00
2026-06-08 02:39:44 +08:00

LanMountainDesktop.AirAppSdk

Official SDK for developing AirApps (Lightweight Applications) for LanMountainDesktop.

What is an AirApp?

AirApp is the next-generation application framework for LanMountainDesktop. It provides a unified development experience for creating:

  • Desktop Components - Widgets that live on the desktop
  • Window Applications - Standalone windowed apps
  • Background Services - Services that run in the background
  • Hybrid Apps - Apps that combine multiple modes

Quick Start

Installation

# Install the SDK package
dotnet add package LanMountainDesktop.AirAppSdk

Create Your First AirApp

  1. Create a new project
dotnet new classlib -n MyFirstAirApp
cd MyFirstAirApp
dotnet add package LanMountainDesktop.AirAppSdk
  1. Create the entry point
using LanMountainDesktop.AirAppSdk;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace MyFirstAirApp;

[AirAppEntrance]
public class MyAirApp : AirAppBase
{
    public override void Initialize(HostBuilderContext context, IServiceCollection services)
    {
        // Register a desktop component
        services.AddAirAppComponent<MyWidget>("my-widget", "My Widget");
    }
}
  1. Create a widget
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using LanMountainDesktop.AirAppSdk;

namespace MyFirstAirApp;

public class MyWidget : AirAppWidgetBase
{
    public MyWidget()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        // Simple widget with a TextBlock
        Content = new TextBlock
        {
            Text = "Hello from AirApp!",
            HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
            VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
        };
    }

    protected override void OnAttachedCore()
    {
        // Called when widget is added to desktop
        Context.Logger.Info("My widget attached!");
    }
}
  1. Create manifest file (airapp.json)
{
  "id": "com.example.myfirstairapp",
  "name": "My First AirApp",
  "version": "1.0.0",
  "apiVersion": "6.0.0",
  "author": "Your Name",
  "description": "My first AirApp for LanMountainDesktop",
  "entranceAssembly": "MyFirstAirApp.dll",
  "runtime": {
    "mode": "in-process"
  }
}
  1. Build the project
dotnet build -c Release

This will produce a .laapp package in bin/Release/net10.0/MyFirstAirApp.laapp.

Core Concepts

AirAppBase

The entry point for your AirApp. Override Initialize() to register components and services:

[AirAppEntrance]
public class MyAirApp : AirAppBase
{
    public override void Initialize(HostBuilderContext context, IServiceCollection services)
    {
        // Register components
        services.AddAirAppComponent<MyWidget>("widget-id", "Widget Name");
        
        // Register windows
        services.AddAirAppWindow<MyWindow>("window-id", "Window Name");
        
        // Register your services
        services.AddSingleton<IMyService, MyService>();
    }

    public override async Task OnStartedAsync(IAirAppRuntimeContext context)
    {
        // Runtime initialization
        context.Logger.Info("AirApp started!");
    }
}

Desktop Components

Create widgets that appear on the desktop:

public class ClockWidget : AirAppWidgetBase
{
    private TextBlock _timeText;

    public ClockWidget()
    {
        _timeText = new TextBlock();
        Content = _timeText;
        
        // Update every second
        DispatcherTimer.Run(() =>
        {
            _timeText.Text = DateTime.Now.ToString("HH:mm:ss");
            return true;
        }, TimeSpan.FromSeconds(1));
    }

    protected override void OnAppearanceChangedCore(AirAppAppearanceSnapshot snapshot)
    {
        // Respond to theme changes
        _timeText.Foreground = new SolidColorBrush(snapshot.ForegroundColor);
    }
}

Windows

Create standalone windows:

public class MyWindow : AirAppWindowBase
{
    public override AirAppWindowDescriptor Descriptor => new()
    {
        Title = "My Window",
        Width = 800,
        Height = 600,
        ChromeMode = AirAppWindowChromeMode.Standard,
        CanResize = true
    };

    public MyWindow()
    {
        Content = new TextBlock { Text = "Hello from window!" };
    }

    public override async Task OnWindowOpeningAsync()
    {
        // Async initialization before window opens
        await LoadDataAsync();
    }
}

Runtime Context

Access runtime services:

protected override async Task OnStartedAsync(IAirAppRuntimeContext context)
{
    // Get data directories
    var dataDir = context.DataDirectory;
    var cacheDir = context.CacheDirectory;
    
    // Use services
    var myService = context.Services.GetService<IMyService>();
    
    // Log messages
    context.Logger.Info("AirApp started!");
    
    // Open a window
    await context.OpenWindowAsync("my-window");
    
    // Subscribe to messages
    context.MessageBus.Subscribe("theme-changed", payload =>
    {
        context.Logger.Info("Theme changed!");
    });
}

API Reference

Core Interfaces

  • IAirApp - AirApp entry point
  • IAirAppWidget - Desktop component widget
  • IAirAppWindow - Window application
  • IAirAppRuntimeContext - Runtime services and context
  • IAirAppComponentContext - Component instance context

Base Classes

  • AirAppBase - Base implementation of IAirApp
  • AirAppWidgetBase - Base class for widgets
  • AirAppWindowBase - Base class for windows

Configuration

  • AirAppManifest - Manifest file structure
  • AirAppComponentOptions - Component registration options
  • AirAppWindowDescriptor - Window configuration
  • AirAppRuntimeMode - Runtime isolation modes

Services

  • IAirAppLogger - Logging service
  • IAirAppMessageBus - Inter-app messaging
  • IAirAppAppearanceContext - Theme and appearance

Runtime Modes

In-Process (Default)

Best performance, runs in the host process:

{
  "runtime": {
    "mode": "in-process"
  }
}

Isolated Background

Runs in a separate background process:

{
  "runtime": {
    "mode": "isolated-background"
  }
}

Isolated Window

Runs in a completely isolated window process:

{
  "runtime": {
    "mode": "isolated-window"
  }
}

Packaging

Your AirApp is automatically packaged as a .laapp file when you build:

dotnet build -c Release

The package includes:

  • All assemblies
  • The airapp.json manifest
  • Any additional resources

Migration from Plugin SDK v5

If you're migrating from the older Plugin SDK:

  1. Update package reference:

    <!-- Old -->
    <PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
    
    <!-- New -->
    <PackageReference Include="LanMountainDesktop.AirAppSdk" Version="6.0.0" />
    
  2. Update manifest file: plugin.jsonairapp.json

  3. Update namespaces:

    // Old
    using LanMountainDesktop.PluginSdk;
    [PluginEntrance]
    public class Plugin : PluginBase { }
    
    // New
    using LanMountainDesktop.AirAppSdk;
    [AirAppEntrance]
    public class MyAirApp : AirAppBase { }
    
  4. Update API calls (mostly compatible, minor naming changes)

Examples

See the samples/ directory for complete examples:

  • SimpleWidget - Basic desktop component
  • ClockWidget - Time display with auto-update
  • WindowApp - Standalone window application
  • HybridApp - Component + window combination

Documentation

Support

License

MIT License - See LICENSE file for details