AI action panel improvements.

This commit is contained in:
Burak Kaan Köse
2026-04-04 01:34:57 +02:00
parent 1211e9b28a
commit 1667aa34db
12 changed files with 330 additions and 87 deletions
+80 -68
View File
@@ -143,71 +143,50 @@
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
<StackPanel
<Grid
x:Name="ReadyPanel"
Spacing="8"
ColumnSpacing="12"
Visibility="Collapsed">
<!-- Row 1: Action tabs + usage -->
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Column 1: Action tabs -->
<controls:Segmented
x:Name="ActionSelector"
Height="30"
VerticalAlignment="Center"
SelectionChanged="ActionSelector_SelectionChanged"
Style="{StaticResource ButtonSegmentedStyle}">
<controls:SegmentedItem
x:Name="TranslateSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureTranslate, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Switch" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
<controls:SegmentedItem
x:Name="RewriteSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureRewrite, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Edit" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
<controls:SegmentedItem
x:Name="SummarizeSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureSummarize, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Bullets" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
</controls:Segmented>
<controls:Segmented
x:Name="ActionSelector"
Height="30"
VerticalAlignment="Center"
SelectionChanged="ActionSelector_SelectionChanged"
Style="{StaticResource ButtonSegmentedStyle}">
<controls:SegmentedItem
x:Name="TranslateSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureTranslate, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Switch" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
<controls:SegmentedItem
x:Name="RewriteSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureRewrite, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Edit" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
<controls:SegmentedItem
x:Name="SummarizeSegment"
Padding="12,6"
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureSummarize, Mode=OneWay}">
<controls:SegmentedItem.Icon>
<SymbolIcon Symbol="Bullets" />
</controls:SegmentedItem.Icon>
</controls:SegmentedItem>
</controls:Segmented>
<StackPanel
Grid.Column="2"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<ProgressBar
x:Name="UsageProgressBar"
Width="100"
VerticalAlignment="Center"
Maximum="1000"
Value="0" />
<TextBlock
x:Name="UsageSummaryTextBlock"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</Grid>
<!-- Row 2: Action-specific options -->
<Grid ColumnSpacing="8">
<!-- Column 2: Action-specific options -->
<Grid Grid.Column="1" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
@@ -284,11 +263,24 @@
x:Name="SummarizeOptionsPanel"
Spacing="8"
Visibility="Collapsed">
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind domain:Translator.Composer_AiSummarizeDescription, Mode=OneWay}" />
<StackPanel Orientation="Horizontal" Spacing="4">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind domain:Translator.Composer_AiTranslateLanguage, Mode=OneWay}" />
<ComboBox
x:Name="SummarizeLanguageComboBox"
MinWidth="120"
SelectionChanged="SummarizeLanguageComboBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="models:AiTranslateLanguageOption">
<TextBlock Text="{x:Bind Label}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button
x:Name="RunSummarizeButton"
HorizontalAlignment="Left"
@@ -306,10 +298,30 @@
ToolTipService.ToolTip="{x:Bind domain:Translator.Composer_AiSummarize, Mode=OneWay}"
Visibility="Collapsed" />
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
<!-- Column 3: Progress -->
<StackPanel
Grid.Column="2"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<ProgressBar
x:Name="UsageProgressBar"
Width="100"
VerticalAlignment="Center"
Maximum="1000"
Value="0" />
<TextBlock
x:Name="UsageSummaryTextBlock"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</Border>
@@ -25,6 +25,7 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
private readonly IStoreManagementService _storeManagementService = App.Current.Services.GetRequiredService<IStoreManagementService>();
private readonly IMailDialogService _dialogService = App.Current.Services.GetRequiredService<IMailDialogService>();
private readonly IAiActionOptionsService _optionsService = App.Current.Services.GetRequiredService<IAiActionOptionsService>();
private readonly IPreferencesService _preferencesService = App.Current.Services.GetRequiredService<IPreferencesService>();
private bool _disposedValue;
private bool _isRefreshing;
@@ -43,6 +44,8 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
public AiTranslateLanguageOption? SelectedTranslateLanguageOption { get; set; }
public AiTranslateLanguageOption? SelectedSummarizeLanguageOption { get; set; }
public AiRewriteModeOption? SelectedRewriteModeOption { get; set; }
public AiActionsPanel()
@@ -90,19 +93,33 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
{
// Save current selections before replacing ItemsSource (which clears SelectedItem).
var previousTranslateCode = SelectedTranslateLanguageOption?.Code;
var previousSummarizeCode = SelectedSummarizeLanguageOption?.Code;
var previousRewriteMode = SelectedRewriteModeOption?.Mode;
var preferredTranslateCode = string.IsNullOrWhiteSpace(previousTranslateCode)
? _preferencesService.AiDefaultTranslationLanguageCode
: previousTranslateCode;
var preferredSummarizeCode = string.IsNullOrWhiteSpace(previousSummarizeCode)
? _preferencesService.AiSummarizeLanguageCode
: previousSummarizeCode;
_translateOptions = _optionsService.GetTranslateLanguageOptions();
_rewriteOptions = _optionsService.GetRewriteModeOptions();
TranslateLanguageComboBox.ItemsSource = _translateOptions;
SummarizeLanguageComboBox.ItemsSource = _translateOptions;
RewriteModeComboBox.ItemsSource = _rewriteOptions;
// Restore selection by matching on value, falling back to first item.
SelectedTranslateLanguageOption = FindOption(_translateOptions, o => o.Code == previousTranslateCode) ?? (_translateOptions.Count > 0 ? _translateOptions[0] : null);
SelectedTranslateLanguageOption = FindOption(_translateOptions, o => o.Code == preferredTranslateCode)
?? FindOption(_translateOptions, o => o.Code == "en-US")
?? (_translateOptions.Count > 0 ? _translateOptions[0] : null);
SelectedSummarizeLanguageOption = FindOption(_translateOptions, o => o.Code == preferredSummarizeCode)
?? FindOption(_translateOptions, o => o.Code == "en-US")
?? (_translateOptions.Count > 0 ? _translateOptions[0] : null);
SelectedRewriteModeOption = FindOption(_rewriteOptions, o => o.Mode == previousRewriteMode) ?? (_rewriteOptions.Count > 0 ? _rewriteOptions[0] : null);
TranslateLanguageComboBox.SelectedItem = SelectedTranslateLanguageOption;
SummarizeLanguageComboBox.SelectedItem = SelectedSummarizeLanguageOption;
RewriteModeComboBox.SelectedItem = SelectedRewriteModeOption;
UpdateRewriteOptionState();
}
@@ -293,6 +310,7 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
BusyProgressBar.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
ActionSelector.IsEnabled = !isBusy;
TranslateLanguageComboBox.IsEnabled = !isBusy;
SummarizeLanguageComboBox.IsEnabled = !isBusy;
RewriteModeComboBox.IsEnabled = !isBusy;
CustomRewriteTextBox.IsEnabled = !isBusy;
RunTranslateButton.IsEnabled = !isBusy;
@@ -426,6 +444,7 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
if (TranslateLanguageComboBox.SelectedItem is AiTranslateLanguageOption option)
{
SelectedTranslateLanguageOption = option;
_preferencesService.AiDefaultTranslationLanguageCode = option.Code;
}
}
@@ -438,6 +457,15 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
}
}
private void SummarizeLanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (SummarizeLanguageComboBox.SelectedItem is AiTranslateLanguageOption option)
{
SelectedSummarizeLanguageOption = option;
_preferencesService.AiSummarizeLanguageCode = option.Code;
}
}
private void UpdateRewriteOptionState()
{
var isCustom = SelectedRewriteModeOption?.IsCustom ?? false;
@@ -500,6 +528,12 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
return;
}
if (action == AiActionType.Summarize && SelectedSummarizeLanguageOption == null)
{
_dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, Translator.WinoAccount_Error_ValidationFailed, InfoBarMessageType.Error);
return;
}
if (action == AiActionType.Translate)
{
var cachedTranslation = await HtmlHost.TryGetCachedTranslationHtmlAsync(SelectedTranslateLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true);
@@ -539,7 +573,7 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
{
AiActionType.Translate => await _profileService.TranslateAsync(html, SelectedTranslateLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true),
AiActionType.Rewrite => await _profileService.RewriteAsync(html, ResolveRewriteMode(), cancellationToken).ConfigureAwait(true),
AiActionType.Summarize => await _profileService.SummarizeAsync(html, cancellationToken).ConfigureAwait(true),
AiActionType.Summarize => await _profileService.SummarizeAsync(html, SelectedSummarizeLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true),
_ => ApiEnvelope<AiTextResultDto>.Failure(ApiErrorCodes.ValidationFailed)
};
@@ -684,7 +718,11 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
try
{
var path = await _dialogService.PickFilePathAsync(HtmlHost.GetSuggestedSummaryFileName());
var configuredSummarySavePath = _preferencesService.AiSummarySavePath;
var path = !string.IsNullOrWhiteSpace(configuredSummarySavePath) && Directory.Exists(configuredSummarySavePath)
? Path.Combine(configuredSummarySavePath, HtmlHost.GetSuggestedSummaryFileName())
: await _dialogService.PickFilePathAsync(HtmlHost.GetSuggestedSummaryFileName());
if (string.IsNullOrWhiteSpace(path))
{
args.Cancel = true;