<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>

    <!--
      The project is named for its layer and the executable is named for the product. Users see the
      executable — in Task Manager, in a shortcut's target, in the SmartScreen dialog an unsigned
      installer raises — and DodoSSH.Client.App.exe reads as an implementation detail leaking out.

      Safe to change now and not later: it becomes the main executable recorded in every Velopack
      package, and changing it after a release means the updater looks for an executable that is no
      longer there. Nothing else depends on the name — no avares://DodoSSH.Client.App URI exists, the
      window icon is the assembly-relative /Assets/dodossh.ico, and WindowsDeviceKeyStore names its
      CNG key with a literal.
    -->
    <AssemblyName>DodoSSH</AssemblyName>

    <!--
      No RuntimeIdentifiers here, and that is the considered answer rather than an omission.

      Declaring win-x64 is the obvious way to let a self-contained publish restore, and it was tried:
      it works, and it also writes a net10.0/win-x64 target into the lock file of every project this
      one references transitively — which includes DodoSSH.Contracts and DodoSSH.Crypto, which the
      server builds too. The API's Dockerfile then restores those projects with no RID and locked
      mode, and fails NU1004 on a lock file that has grown a runtime identifier the server knows
      nothing about. The desktop head's packaging would have broken the server's image build.

      So the RID stays out of the committed state entirely, and the publish that needs one asks for
      it unlocked — see scripts/release-windows.ps1 and the CI step that proves the same thing. The
      locked restore that gates every ordinary build is untouched, which is the property worth
      keeping. See docs/platform-flags.md.
    -->

    <!--
      The icon on the executable itself — what Explorer, the Start menu and a pinned taskbar button
      draw, all of which read it from the PE resource and never start the process. Window.Icon in
      MainWindow.axaml is a separate thing that only exists once the application is running; both are
      needed, and both point at this file.
    -->
    <ApplicationIcon>Assets/dodossh.ico</ApplicationIcon>

    <!--
      ============ WHICH CHANNEL THIS BUILD BELONGS TO ============

      The same split the Android head has, for the same reason and with one difference worth stating up
      front: Android gets separation for free, because the platform refuses an update signed by a
      different key, so its two channels cannot replace one another whatever anybody does. Nothing
      refuses anything here. Velopack applies what its feed serves, so the separation has to be built:
      two pack ids, two Velopack channels, two feeds, and a profile directory each.

      release — DodoSSH.Desktop, Velopack channel win, read from the newest non-prerelease release.
                Cut from a v* tag by scripts/release-windows.ps1, by a person. See ADR 0013 rule 3.
      nightly — DodoSSH.Desktop.Nightly, Velopack channel win-nightly, read from a prerelease release
                CI replaces on every push to main.

      Default release, so an unqualified `dotnet build` is the real application and the nightly is the
      one you have to ask for.

      What this property does *not* decide is the pack id or the title. Those are arguments to vpk and
      live where the packaging happens — in ci.yml for the nightly and in the release script for the
      release. Putting them here would suggest the build knows which package it will end up inside,
      and it does not.
    -->
    <DodoChannel Condition="'$(DodoChannel)' == ''">release</DodoChannel>

    <!--
      False here, unlike every server project. The root Directory.Build.props sets it true because
      the API is container-hosted, UTC-only and has no business formatting anything for a human.
      This process does: it shows timestamps and host names to a person who expects their own
      locale's conventions. Invariant globalization would quietly render every date in a format
      that is correct for nobody.
    -->
    <InvariantGlobalization>false</InvariantGlobalization>
  </PropertyGroup>

  <ItemGroup>
    <!--
      Named rather than globbed as Assets/**, because the folder also holds the script that draws the
      icon and a build has no reason to carry a copy of it around inside the binary.
    -->
    <AvaloniaResource Include="Assets/dodossh.ico" />
  </ItemGroup>

  <ItemGroup>
    <!--
      Which channel this build belongs to, carried in the assembly the same way the Android head carries
      it. Metadata rather than a compile-time constant for the reason stated there: the updater needs the
      string rather than a branch, and a value baked into the assembly is one a crash report can be asked
      for. See DesktopChannel, which is the only thing that reads it.
    -->
    <AssemblyMetadata Include="DodoChannel" Value="$(DodoChannel)" />
  </ItemGroup>

  <!--
    Two native symbol files, and they are the reason a self-contained publish weighed 227 MB.

    Measured on a win-x64 publish: libSkiaSharp.pdb is 80.1 MB and libHarfBuzzSharp.pdb is 19.9 MB, so
    the two of them are 100 MB of debug symbols for third-party native code nobody here will ever step
    through. Dropping them takes the publish to about 127 MB, which is most of what a first install
    costs somebody on a slow connection.

    Our own symbols stay, and the distinction is the point rather than a compromise. All fifteen managed
    PDBs together are 0.93 MB, and with them present an Exception.ToString() carries file names and line
    numbers — which for a self-hosted product is the whole diagnostic channel, because the way a fault
    gets reported is a user pasting a stack into an issue.

    Named one by one instead of matched by a pattern. A rule like "drop every .pdb whose assembly is
    native" would be shorter and would silently start dropping ours the day a managed library ships a
    file this heuristic misreads, and a build that quietly stops carrying line numbers is not a thing
    anybody notices until they need them.
  -->
  <Target Name="DropNativeSymbolsFromPublish" AfterTargets="ComputeResolvedFilesToPublishList">
    <ItemGroup>
      <ResolvedFileToPublish
        Remove="@(ResolvedFileToPublish)"
        Condition="'%(Filename)%(Extension)' == 'libSkiaSharp.pdb'
                or '%(Filename)%(Extension)' == 'libHarfBuzzSharp.pdb'" />
    </ItemGroup>
  </Target>

  <ItemGroup>
    <PackageReference Include="Avalonia" />
    <PackageReference Include="Avalonia.Desktop" />
    <PackageReference Include="Avalonia.Themes.Fluent" />
    <PackageReference Include="Avalonia.Fonts.Inter" />
    <PackageReference Include="Avalonia.Controls.WebView" />
    <PackageReference Include="CommunityToolkit.Mvvm" />
    <!--
      Here and in no other project. The Android head must never reference it — that head's
      distribution is settled by ADR 0011 and has no updater — and DodoSSH.Client.Shell is shared
      between the two heads, so the one file that names Velopack lives in Platform/ beside
      WindowsDeviceKeyStore, which is the same shape of thing: a Windows-only implementation of an
      interface declared in DodoSSH.Client.Session.
    -->
    <PackageReference Include="Velopack" />
  </ItemGroup>

  <ItemGroup>
    <!--
      The shell's view models, the terminal renderer's files and the palette, all shared with the Android
      head. This project is now the desktop *views* and the desktop platform integration, and nothing else.
    -->
    <ProjectReference Include="../DodoSSH.Client.Shell/DodoSSH.Client.Shell.csproj" />
    <ProjectReference Include="../DodoSSH.Client.Import/DodoSSH.Client.Import.csproj" />
    <ProjectReference Include="../DodoSSH.Client.Session/DodoSSH.Client.Session.csproj" />
    <ProjectReference Include="../DodoSSH.Client.Ssh/DodoSSH.Client.Ssh.csproj" />
    <ProjectReference Include="../DodoSSH.Client.ObjectStore/DodoSSH.Client.ObjectStore.csproj" />
    <ProjectReference Include="../DodoSSH.Client.Terminal/DodoSSH.Client.Terminal.csproj" />
    <ProjectReference Include="../DodoSSH.Client.Transfer/DodoSSH.Client.Transfer.csproj" />
  </ItemGroup>

  <ItemGroup>
    <!--
      The view models are plain CommunityToolkit.Mvvm objects and need no Avalonia to run, so the shell's
      state machine is testable as ordinary code. That is the whole reason the sign-in step is a delegate.
    -->
    <InternalsVisibleTo Include="DodoSSH.Client.App.Tests" />

    <!--
      The layout harness needs the views and the application class themselves, not just the view models:
      its whole job is to lay out the real XAML and measure it.
    -->
    <InternalsVisibleTo Include="DodoSSH.Client.App.Layout.Tests" />
  </ItemGroup>

</Project>

