Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to Aperture Image Viewer are documented here. The format fol

## [Unreleased]

## [0.8.1-beta1] - 2026-08-21

### Added
- **About + updater** on the hamburger menu — current version (installed/portable), GitHub
release check, Update / Update (prerelease) when a newer build is available, progress and
errors. Running from AppData swaps in place (Midget-style rename dance); a portable copy
downloads the new exe next to the current one.
- **AppData install** — hamburger **Install Aperture on this PC…** copies to
`%LocalAppData%\Programs\Aperture\`, adds a Start menu shortcut (optional Desktop), and
**Uninstall…** reverses it. No `.md` file association — Aperture is not an editor.
- **Start with Windows** — opt-in checkbox on the same Settings surface. Writes or deletes
`HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Aperture`; off by default. After
install or update the Run value is rewritten to the AppData exe so logon does not keep a
Downloads path.

## [0.8.0-beta1] - 2026-07-14

### Added
Expand Down
16 changes: 10 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ dates. Items are checked off as they ship (each lands a `CHANGELOG.md` entry whe

## Distribution & lifecycle

- [ ] **Real installer & updater** — a proper Windows installer (Start-menu entry, clean uninstall,
file associations where they make sense) to replace the bare framework-dependent single-file `.exe`,
plus an in-app update check/apply so test users don't have to re-download by hand each beta.
- [x] **AppData install + Start menu** — hamburger Install copies to
`%LocalAppData%\Programs\Aperture\Aperture.exe`, adds Start-menu (optional Desktop)
shortcuts, and Uninstall reverses it. In-app update check/apply lives on the hamburger
About surface: in-place swap when running from that copy, portable apply otherwise.

- [ ] **Start with Windows + tray behavior** — an opt-in "launch at login" setting, and an option to
close/minimize to the background / system tray instead of exiting, so Aperture can stay warm for
instant opens. Both **off by default**.
- [x] **Start with Windows** — opt-in "launch at login" checkbox on the hamburger Settings
surface (`HKCU\Software\Microsoft\Windows\CurrentVersion\Run`). Off by default. Survives
install/update by rewriting the Run value to the AppData exe.

- [ ] **Tray behavior** — option to close/minimize to the background / system tray instead of
exiting, so Aperture can stay warm for instant opens. Off by default.

## Tags & metadata

Expand Down
9 changes: 8 additions & 1 deletion src/Aperture.App/Aperture.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@
<UseWPF>true</UseWPF>
<ApplicationIcon>Assets\aperture.ico</ApplicationIcon>
<AssemblyName>Aperture</AssemblyName>
<Version>0.8.0-beta1</Version>
<Version>0.8.1-beta1</Version>
<AssemblyTitle>Aperture Image Viewer</AssemblyTitle>
<Product>Aperture Image Viewer</Product>
<Description>A fast local image &amp; video browser for Windows.</Description>
<Company>Funcular Labs</Company>
<Authors>Funcular Labs</Authors>
<Copyright>© 2026 Funcular Labs</Copyright>
<!-- Don't append the +git-sha suffix to InformationalVersion — it clutters
the About line and the update check parses it as the running version. -->
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="Aperture.Core.Tests" />
</ItemGroup>

<ItemGroup>
<Resource Include="Assets\aperture.ico" />
<Resource Include="Assets\mascot.png" />
Expand Down
12 changes: 12 additions & 0 deletions src/Aperture.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Windows;
using System.Windows.Threading;
using Aperture.App.Services;
using Aperture.App.Updates;
using Aperture.App.ViewModels;
using Aperture.Core.Library;
using Aperture.Core.Storage;
Expand Down Expand Up @@ -30,8 +31,19 @@ protected override void OnStartup(StartupEventArgs e)
if (string.IsNullOrWhiteSpace(overrideDir))
LegacyDataMigration.Run(AperturePaths.DefaultDataDir, AperturePaths.LegacyReelDataDir);

// A "move" install launches the AppData copy with --finish-move <download>
// so it can delete the original once that process has exited.
var args = e.Args;
for (var i = 0; i < args.Length; i++)
{
if (args[i] == "--finish-move" && i + 1 < args.Length)
RegistrationService.FinishMove(args[++i]);
}

_library = new LibraryService(dataDir);
var thumbnails = new ThumbnailService(_library);
UpdateService.CleanupOldBinaries();
RegistrationService.RefreshAutostartToInstalledCopy();
_viewModel = new MainViewModel(_library, thumbnails);

var window = new MainWindow { DataContext = _viewModel };
Expand Down
55 changes: 49 additions & 6 deletions src/Aperture.App/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -353,23 +353,49 @@
</Popup>
<Popup IsOpen="{Binding IsChecked, ElementName=SettingsToggle}"
PlacementTarget="{Binding ElementName=SettingsToggle}" Placement="Bottom"
StaysOpen="False" AllowsTransparency="True" HorizontalOffset="-160">
StaysOpen="False" AllowsTransparency="True" HorizontalOffset="-180"
Opened="OnSettingsOpened">
<Border Background="{StaticResource Panel}" BorderBrush="{StaticResource Line}"
BorderThickness="1" CornerRadius="8" Padding="16" Width="280"
BorderThickness="1" CornerRadius="8" Padding="16" Width="320"
Margin="8" SnapsToDevicePixels="True">
<Border.Effect>
<DropShadowEffect Color="#22000000" BlurRadius="16" ShadowDepth="2" Direction="270" />
</Border.Effect>
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="640"
HorizontalScrollBarVisibility="Disabled">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,14">
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
<Image Source="Assets/mascot.png" Width="34" Height="34" />
<StackPanel VerticalAlignment="Center" Margin="10,0,0,0">
<TextBlock Text="{Binding AppVersion}" Foreground="{StaticResource Ink}"
FontWeight="SemiBold" FontSize="14" />
FontWeight="SemiBold" FontSize="13" TextWrapping="Wrap" />
<TextBlock Text="A fast local image &amp; video browser" Foreground="{StaticResource Muted}"
FontSize="11" />
</StackPanel>
</StackPanel>
<TextBlock Text="{Binding OnDiskVersionText}" Foreground="{StaticResource Accent}"
FontSize="11" TextWrapping="Wrap" Margin="0,0,0,8"
Visibility="{Binding ShowOnDiskVersion, Converter={StaticResource BoolToVis}}" />
<TextBlock Text="{Binding NewestReleaseText}" Foreground="{StaticResource Muted}"
FontSize="11" TextWrapping="Wrap" Margin="0,0,0,4" />
<Button Content="Update" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Padding="8,5" Margin="0,0,0,6" Command="{Binding UpdateStableCommand}"
IsEnabled="{Binding CanApplyUpdate}" Cursor="Hand"
Visibility="{Binding ShowStableUpdate, Converter={StaticResource BoolToVis}}"
Foreground="{StaticResource Ink}" />
<TextBlock Text="{Binding NewestPrereleaseText}" Foreground="{StaticResource Muted}"
FontSize="11" TextWrapping="Wrap" Margin="0,0,0,4"
Visibility="{Binding ShowPrereleaseRow, Converter={StaticResource BoolToVis}}" />
<Button Content="Update (prerelease)" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Padding="8,5" Margin="0,0,0,6" Command="{Binding UpdatePrereleaseCommand}"
IsEnabled="{Binding CanApplyUpdate}" Cursor="Hand"
Visibility="{Binding ShowPrereleaseUpdate, Converter={StaticResource BoolToVis}}"
Foreground="{StaticResource Ink}" />
<TextBlock Text="{Binding UpdateMessage}" Foreground="{StaticResource Accent}"
FontSize="11" TextWrapping="Wrap" Margin="0,0,0,4"
Visibility="{Binding ShowUpdateMessage, Converter={StaticResource BoolToVis}}" />
<ProgressBar Height="6" Margin="0,0,0,10" IsIndeterminate="True"
Visibility="{Binding UpdateBusy, Converter={StaticResource BoolToVis}}" />

<TextBlock Text="VIEW" Foreground="{StaticResource Muted}" FontSize="11"
FontWeight="SemiBold" Margin="0,0,0,8" />
Expand Down Expand Up @@ -397,7 +423,11 @@
Margin="22,2,0,10" />

<CheckBox Content="Group into date sections" IsChecked="{Binding GroupByDate}"
Margin="0,0,0,12" />
Margin="0,0,0,10" />

<CheckBox Content="Start with Windows" IsChecked="{Binding StartWithWindows}"
Margin="0,0,0,12"
ToolTip="Launch Aperture when you sign in to Windows." />

<TextBlock Text="Caption format" Foreground="{StaticResource Ink}" FontSize="12"
FontWeight="SemiBold" Margin="0,0,0,4" />
Expand All @@ -423,11 +453,24 @@
Foreground="{StaticResource Ink}"
ToolTip="Merge tags &amp; notes from a JSON file (upsert; remaps folders by alias)." />
<Button Content="📖 View README (help)" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="8,6" Command="{Binding OpenReadmeCommand}"
Padding="8,6" Margin="0,0,0,6" Command="{Binding OpenReadmeCommand}"
Background="Transparent" BorderThickness="0" Cursor="Hand"
Foreground="{StaticResource Ink}" />
<Button Content="Install Aperture on this PC…" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="8,6" Margin="0,0,0,6" Command="{Binding InstallCommand}"
Background="Transparent" BorderThickness="0" Cursor="Hand"
Foreground="{StaticResource Ink}"
Visibility="{Binding ShowInstall, Converter={StaticResource BoolToVis}}"
ToolTip="Copy Aperture to AppData and add a Start menu shortcut." />
<Button Content="Uninstall…" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="8,6" Command="{Binding UninstallCommand}"
Background="Transparent" BorderThickness="0" Cursor="Hand"
Foreground="{StaticResource Ink}"
Visibility="{Binding ShowUninstall, Converter={StaticResource BoolToVis}}"
ToolTip="Remove Start menu / Desktop shortcuts and the AppData copy." />

</StackPanel>
</ScrollViewer>
</Border>
</Popup>

Expand Down
3 changes: 3 additions & 0 deletions src/Aperture.App/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,9 @@ private void OnGridSelectionChanged(object sender, System.Windows.Controls.Selec
/// <summary>Closes the settings/overflow popup after Refresh runs (it opens no dialog to steal focus).</summary>
private void OnRefreshMenuClick(object sender, RoutedEventArgs e) => SettingsToggle.IsChecked = false;

/// <summary>Hamburger opened: refresh Start-with-Windows from the Run key and check GitHub for updates.</summary>
private void OnSettingsOpened(object sender, EventArgs e) => ViewModel?.OnSettingsOpened();

/// <summary>
/// Explorer-style right-click: clicking a tile that isn't in the current selection
/// selects just it; clicking within the selection keeps it, so the context menu
Expand Down
Loading
Loading