Skip to content
Open
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
4 changes: 3 additions & 1 deletion agents.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PicView Development Guidelines
# PicView Development Guidelines

## Build & Configuration

Expand Down Expand Up @@ -28,6 +28,8 @@ dotnet build PicView.Tests\PicView.Tests.csproj

### Running Tests

- **Agent Guideline**: When running `dotnet test`, never schedule polling/timeout timers (`schedule`). Allow background execution to complete indefinitely and rely on reactive task completion notifications.

Run all tests:

```powershell
Expand Down
47 changes: 22 additions & 25 deletions src/PicView.Avalonia/FileSystem/FilePickerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,8 @@ public async Task SelectAndLoadFile(MainWindow mainWindow, MainWindowViewModel v

public async Task<string?> SelectFile()
{
return await Dispatcher.UIThread.InvokeAsync(async () =>
{
var file = await SelectIStorageFile().ConfigureAwait(false);
return file?.Path.LocalPath;
});
var file = await SelectIStorageFile().ConfigureAwait(false);
return file?.Path.LocalPath;
}

private async Task<IStorageFile?> SelectIStorageFile()
Expand Down Expand Up @@ -171,26 +168,23 @@ public async ValueTask<bool> PickAndSaveFileAsAsync(string? fileName, MainWindow

public async Task<string> SelectDirectory()
{
return await Dispatcher.UIThread.InvokeAsync(async () =>
var provider = GetStorageProvider();
if (provider is null) return string.Empty;

var options = new FolderPickerOpenOptions
{
var provider = GetStorageProvider();
if (provider is null) return string.Empty;

var options = new FolderPickerOpenOptions
{
Title = StringExtensions.CombineWithAppName(TranslationManager.Translation.Folder),
AllowMultiple = false
};

var directories = await ExecuteOnUIThread(() => provider.OpenFolderPickerAsync(options));

if (directories is null || directories.Count <= 0)
{
return string.Empty;
}

return directories[0].Path.LocalPath;
});
Title = StringExtensions.CombineWithAppName(TranslationManager.Translation.Folder),
AllowMultiple = false
};

var directories = await ExecuteOnUIThread(() => provider.OpenFolderPickerAsync(options)).ConfigureAwait(false);

if (directories is null || directories.Count <= 0)
{
return string.Empty;
}

return directories[0].Path.LocalPath;
}

private IStorageProvider? GetStorageProvider()
Expand Down Expand Up @@ -225,7 +219,10 @@ private static string GetSuggestedFileName(string? fileName, string? ext)

private static async Task<T> ExecuteOnUIThread<T>(Func<Task<T>> action)
{
// Try to use file picker in Dispatcher #228
if (Dispatcher.UIThread.CheckAccess())
{
return await action().ConfigureAwait(false);
}
return await Dispatcher.UIThread.InvokeAsync(action).ConfigureAwait(false);
}
}
9 changes: 8 additions & 1 deletion src/PicView.Avalonia/FileSystem/FileSavingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,14 @@ public async ValueTask<bool> SaveFileAs(MainWindowViewModel vm)

public async ValueTask<bool> SaveFileAsync(string? filename, string destination, MainWindowViewModel vm)
{
var core = await Dispatcher.UIThread.InvokeAsync(() => Application.Current?.DataContext as CoreViewModel);
if (Application.Current is null)
{
return false;
}

var core = Dispatcher.UIThread.CheckAccess()
? Application.Current.DataContext as CoreViewModel
: await Dispatcher.UIThread.InvokeAsync(() => Application.Current.DataContext as CoreViewModel);
if (core is null)
{
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/PicView.Avalonia/Input/MainKeyboardShortcuts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static async ValueTask MainWindow_KeysUpAsync(KeyEventArgs e, MainWindowV
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
if (CurrentKeys.Key is Key.LeftAlt or Key.RightAlt)
if (CurrentKeys?.Key is Key.LeftAlt or Key.RightAlt)
{
mainWindowViewModel.TopTitlebarViewModel.ToggleMenu();
}
Expand Down
25 changes: 25 additions & 0 deletions src/PicView.Avalonia/Views/Main/MainView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -1101,5 +1101,30 @@
VerticalAlignment="Center"
Opacity="0"
ZIndex="9" />

<!-- Bottom-right Archive Extraction Progress Indicator -->
<Border
Margin="0,0,16,16"
Padding="8,4"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Background="{DynamicResource AltBackgroundColor}"
BorderBrush="{DynamicResource MainBorderColor}"
BorderThickness="1"
CornerRadius="4"
IsHitTestVisible="False"
IsVisible="{Binding WindowTabs.ActiveTab.Value.ArchiveExtractionProgressText.Value, Mode=OneWay, Converter={x:Static ObjectConverters.IsNotNull}}"
ZIndex="10">
<StackPanel Orientation="Horizontal" Spacing="6" VerticalAlignment="Center">
<Viewbox Width="14" Height="14" VerticalAlignment="Center">
<uc:SpinWaiter />
</Viewbox>
<TextBlock
Classes="txt"
VerticalAlignment="Center"
FontSize="12"
Text="{Binding WindowTabs.ActiveTab.Value.ArchiveExtractionProgressText.Value, Mode=OneWay}" />
</StackPanel>
</Border>
</Panel>
</UserControl>
Loading
Loading