diff --git a/Directory.Packages.props b/Directory.Packages.props
index 700a216d..3c780068 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -33,7 +33,7 @@
-
+
diff --git a/Wino.Core.Domain/Interfaces/IPreferencesService.cs b/Wino.Core.Domain/Interfaces/IPreferencesService.cs
index 9b80f8e2..53645338 100644
--- a/Wino.Core.Domain/Interfaces/IPreferencesService.cs
+++ b/Wino.Core.Domain/Interfaces/IPreferencesService.cs
@@ -67,6 +67,21 @@ public interface IPreferencesService : INotifyPropertyChanged
///
bool IsWinoAccountButtonHidden { get; set; }
+ ///
+ /// Setting: Default target language code used for AI translation actions.
+ ///
+ string AiDefaultTranslationLanguageCode { get; set; }
+
+ ///
+ /// Setting: Preferred target language code for AI summarize actions.
+ ///
+ string AiSummarizeLanguageCode { get; set; }
+
+ ///
+ /// Setting: Preferred folder path used when saving AI summaries.
+ ///
+ string AiSummarySavePath { get; set; }
+
///
/// Serializes the current syncable preferences snapshot.
///
diff --git a/Wino.Core.Domain/Interfaces/IWinoAccountApiClient.cs b/Wino.Core.Domain/Interfaces/IWinoAccountApiClient.cs
index 615de7d6..a76b1764 100644
--- a/Wino.Core.Domain/Interfaces/IWinoAccountApiClient.cs
+++ b/Wino.Core.Domain/Interfaces/IWinoAccountApiClient.cs
@@ -19,7 +19,7 @@ public interface IWinoAccountApiClient
Task> LogoutAsync(string refreshToken, CancellationToken cancellationToken = default);
Task> GetCurrentUserAsync(CancellationToken cancellationToken = default);
Task> GetAiStatusAsync(CancellationToken cancellationToken = default);
- Task> SummarizeAsync(string html, CancellationToken cancellationToken = default);
+ Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default);
Task> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default);
Task> RewriteAsync(string html, string mode, CancellationToken cancellationToken = default);
Task> CreateCollectionsIdTicketAsync(CancellationToken cancellationToken = default);
diff --git a/Wino.Core.Domain/Interfaces/IWinoAccountProfileService.cs b/Wino.Core.Domain/Interfaces/IWinoAccountProfileService.cs
index 66083d43..7857c8cf 100644
--- a/Wino.Core.Domain/Interfaces/IWinoAccountProfileService.cs
+++ b/Wino.Core.Domain/Interfaces/IWinoAccountProfileService.cs
@@ -24,7 +24,7 @@ public interface IWinoAccountProfileService
Task HasActiveAccountAsync();
Task> GetCurrentUserAsync(CancellationToken cancellationToken = default);
Task> GetAiStatusAsync(CancellationToken cancellationToken = default);
- Task> SummarizeAsync(string html, CancellationToken cancellationToken = default);
+ Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default);
Task> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default);
Task> RewriteAsync(string html, string mode, CancellationToken cancellationToken = default);
Task> SyncStoreEntitlementsAsync(CancellationToken cancellationToken = default);
diff --git a/Wino.Core.Domain/Translations/en_US/resources.json b/Wino.Core.Domain/Translations/en_US/resources.json
index a8fd04fa..51c0b3b1 100644
--- a/Wino.Core.Domain/Translations/en_US/resources.json
+++ b/Wino.Core.Domain/Translations/en_US/resources.json
@@ -724,6 +724,16 @@
"SettingsAppPreferences_HideWinoAccountButton_Description": "Hide the title bar profile button that opens the Wino account flyout.",
"SettingsAppPreferences_StoreUpdateNotifications_Title": "Store update notifications",
"SettingsAppPreferences_StoreUpdateNotifications_Description": "Show notifications and footer actions when a Microsoft Store update is available.",
+ "SettingsAppPreferences_AiActions_Title": "AI actions",
+ "SettingsAppPreferences_AiActions_Description": "Choose default AI languages and where summaries should be saved.",
+ "SettingsAppPreferences_AiDefaultTranslationLanguage_Title": "Default translation language",
+ "SettingsAppPreferences_AiDefaultTranslationLanguage_Description": "Pick the default target language used by AI translate actions.",
+ "SettingsAppPreferences_AiSummarizeLanguage_Title": "Summarize language",
+ "SettingsAppPreferences_AiSummarizeLanguage_Description": "Choose the preferred summarize language for future AI summary output.",
+ "SettingsAppPreferences_AiSummarySavePath_Title": "Default summary save path",
+ "SettingsAppPreferences_AiSummarySavePath_Description": "Choose the folder Wino should use by default when saving AI summaries.",
+ "SettingsAppPreferences_AiSummarySavePath_Placeholder": "Use the system default save location",
+ "SettingsAppPreferences_AiSummarySavePath_InvalidHint": "This folder does not exist. The default save location will be used for summaries.",
"SettingsAutoSelectNextItem_Description": "Select the next item after you delete or move a mail.",
"SettingsAutoSelectNextItem_Title": "Auto select next item",
"SettingsAvailableThemes_Description": "Select a theme from Wino's own collection for your taste or apply your own themes.",
@@ -1071,7 +1081,7 @@
"AiActions_SignedOutDescription": "Translate, rewrite, and summarize emails with AI after signing in to your Wino Account and activating the AI Pack add-on.",
"AiActions_NoPackTitle": "AI Pack required",
"AiActions_NoPackDescription": "You're signed in, but AI Pack is not active yet. Purchase it to use Wino's AI translation, rewrite, and summarize tools.",
- "AiActions_UsageSummary": "{0} of {1} requests used this month.",
+ "AiActions_UsageSummary": "{0} of {1} credits used this month.",
"Composer_AiRewritePolite": "Make it polite",
"Composer_AiRewritePoliteDescription": "Softens the wording while keeping the same intent.",
"Composer_AiRewriteAngry": "Make it angry",
@@ -1243,7 +1253,7 @@
"WinoAccount_Management_AiPackPromoTitle": "Unlock AI Pack",
"WinoAccount_Management_AiPackPromoDescription": "Supercharge your email workflow with AI-powered tools. Translate messages into 50+ languages, rewrite for clarity and tone, and get instant summaries of long threads.",
"WinoAccount_Management_AiPackPromoPrice": "$4.99 / mo",
- "WinoAccount_Management_AiPackPromoRequests": "1,000 requests",
+ "WinoAccount_Management_AiPackPromoRequests": "1,000 credits",
"WinoAccount_Management_AiPackGetButton": "Get AI Pack",
"WinoAddOn_AI_PACK_Name": "Wino AI Pack",
"WinoAddOn_AI_PACK_Description": "AI-powered tools for translate, rewrite, and summarize actions in Wino Mail.",
@@ -1256,7 +1266,7 @@
"WinoAccount_Management_StoreSyncFailed": "Your purchase finished, but Wino could not refresh your account benefits yet. Please try again in a moment.",
"WinoAccount_Management_AiPackSubscriptionActive": "Your subscription is active",
"WinoAccount_Management_AiPackRenews": "Renews {0:d}",
- "WinoAccount_Management_AiPackRequestsUsed": "Requests used this month",
+ "WinoAccount_Management_AiPackRequestsUsed": "Credits used this month",
"WinoAccount_Management_AiPackResets": "Resets {0:d}",
"WinoAccount_Management_AiPackUsageLoadFailed": "We had issues loading your AI usage balance.",
"WinoAccount_Management_AiPackFeatureTranslate": "Translate",
diff --git a/Wino.Mail.ViewModels/AppPreferencesPageViewModel.cs b/Wino.Mail.ViewModels/AppPreferencesPageViewModel.cs
index 8f4c2724..4c6ab537 100644
--- a/Wino.Mail.ViewModels/AppPreferencesPageViewModel.cs
+++ b/Wino.Mail.ViewModels/AppPreferencesPageViewModel.cs
@@ -1,10 +1,12 @@
using System.Collections.Generic;
+using System.IO;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Ai;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Translations;
@@ -16,12 +18,14 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
IMailDialogService dialogService,
IPreferencesService preferencesService,
IStartupBehaviorService startupBehaviorService,
- ITranslationService translationService)
+ ITranslationService translationService,
+ IAiActionOptionsService aiActionOptionsService)
{
_dialogService = dialogService;
PreferencesService = preferencesService;
_startupBehaviorService = startupBehaviorService;
_translationService = translationService;
+ _aiActionOptionsService = aiActionOptionsService;
SearchModes =
[
@@ -40,6 +44,7 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
SelectedDefaultSearchMode = SearchModes[(int)PreferencesService.DefaultSearchMode];
SelectedDefaultApplicationMode = ApplicationModes[(int)PreferencesService.DefaultApplicationMode];
EmailSyncIntervalMinutes = PreferencesService.EmailSyncIntervalMinutes;
+ SummarySavePath = PreferencesService.AiSummarySavePath;
}
public IPreferencesService PreferencesService { get; }
@@ -56,6 +61,21 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
[ObservableProperty]
public partial AppLanguageModel SelectedLanguage { get; set; }
+ [ObservableProperty]
+ public partial List AvailableAiLanguages { get; set; } = [];
+
+ [ObservableProperty]
+ public partial AiTranslateLanguageOption SelectedDefaultTranslationLanguage { get; set; }
+
+ [ObservableProperty]
+ public partial AiTranslateLanguageOption SelectedSummarizeLanguage { get; set; }
+
+ [ObservableProperty]
+ public partial string SummarySavePath { get; set; } = string.Empty;
+
+ [ObservableProperty]
+ public partial bool HasInvalidSummarySavePath { get; set; }
+
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorDisabled))]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorEnabled))]
@@ -64,7 +84,9 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
private readonly IMailDialogService _dialogService;
private readonly IStartupBehaviorService _startupBehaviorService;
private readonly ITranslationService _translationService;
+ private readonly IAiActionOptionsService _aiActionOptionsService;
private bool _isLanguageInitialized;
+ private bool _isAiPreferencesInitialized;
private int _emailSyncIntervalMinutes;
private string _selectedDefaultSearchMode;
private string _selectedDefaultApplicationMode;
@@ -110,6 +132,31 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
_ = _translationService.InitializeLanguageAsync(value.Language);
}
+ partial void OnSelectedDefaultTranslationLanguageChanged(AiTranslateLanguageOption value)
+ {
+ if (!_isAiPreferencesInitialized || value == null)
+ return;
+
+ PreferencesService.AiDefaultTranslationLanguageCode = value.Code;
+ }
+
+ partial void OnSelectedSummarizeLanguageChanged(AiTranslateLanguageOption value)
+ {
+ if (!_isAiPreferencesInitialized || value == null)
+ return;
+
+ PreferencesService.AiSummarizeLanguageCode = value.Code;
+ }
+
+ partial void OnSummarySavePathChanged(string value)
+ {
+ if (!_isAiPreferencesInitialized)
+ return;
+
+ PreferencesService.AiSummarySavePath = value ?? string.Empty;
+ RefreshSummarySavePathState();
+ }
+
[RelayCommand]
private async Task ToggleStartupBehaviorAsync()
{
@@ -157,15 +204,56 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
}
}
+ [RelayCommand]
+ private async Task BrowseSummarySavePathAsync()
+ {
+ var pickedPath = await _dialogService.PickWindowsFolderAsync();
+ if (string.IsNullOrWhiteSpace(pickedPath))
+ return;
+
+ await ExecuteUIThread(() => SummarySavePath = pickedPath);
+ }
+
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
- AvailableLanguages = _translationService.GetAvailableLanguages();
- SelectedLanguage = AvailableLanguages.Find(language => language.Language == PreferencesService.CurrentLanguage)
- ?? (AvailableLanguages.Count > 0 ? AvailableLanguages[0] : null);
- _isLanguageInitialized = true;
+ var availableLanguages = _translationService.GetAvailableLanguages();
+ var availableAiLanguages = new List(_aiActionOptionsService.GetTranslateLanguageOptions());
+ var startupBehaviorResult = await _startupBehaviorService.GetCurrentStartupBehaviorAsync();
- StartupBehaviorResult = await _startupBehaviorService.GetCurrentStartupBehaviorAsync();
+ await ExecuteUIThread(() =>
+ {
+ AvailableLanguages = availableLanguages;
+ SelectedLanguage = AvailableLanguages.Find(language => language.Language == PreferencesService.CurrentLanguage)
+ ?? (AvailableLanguages.Count > 0 ? AvailableLanguages[0] : null);
+ _isLanguageInitialized = true;
+
+ AvailableAiLanguages = availableAiLanguages;
+ SelectedDefaultTranslationLanguage = FindAiLanguageOption(PreferencesService.AiDefaultTranslationLanguageCode)
+ ?? FindAiLanguageOption("en-US")
+ ?? (AvailableAiLanguages.Count > 0 ? AvailableAiLanguages[0] : null);
+ SelectedSummarizeLanguage = FindAiLanguageOption(PreferencesService.AiSummarizeLanguageCode)
+ ?? FindAiLanguageOption("en-US")
+ ?? (AvailableAiLanguages.Count > 0 ? AvailableAiLanguages[0] : null);
+ SummarySavePath = PreferencesService.AiSummarySavePath;
+ RefreshSummarySavePathState();
+ _isAiPreferencesInitialized = true;
+
+ StartupBehaviorResult = startupBehaviorResult;
+ });
+ }
+
+ private AiTranslateLanguageOption FindAiLanguageOption(string languageCode)
+ {
+ if (string.IsNullOrWhiteSpace(languageCode))
+ return null;
+
+ return AvailableAiLanguages.Find(option => option.Code == languageCode);
+ }
+
+ private void RefreshSummarySavePathState()
+ {
+ HasInvalidSummarySavePath = !string.IsNullOrWhiteSpace(SummarySavePath) && !Directory.Exists(SummarySavePath);
}
}
diff --git a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml
index b799c1e2..cf49e1f9 100644
--- a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml
+++ b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml
@@ -143,71 +143,50 @@
Style="{StaticResource AccentButtonStyle}" />
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -284,11 +263,24 @@
x:Name="SummarizeOptionsPanel"
Spacing="8"
Visibility="Collapsed">
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
diff --git a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs
index d9b2b383..19b4a71a 100644
--- a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs
+++ b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs
@@ -25,6 +25,7 @@ public sealed partial class AiActionsPanel : UserControl, IDisposable
private readonly IStoreManagementService _storeManagementService = App.Current.Services.GetRequiredService();
private readonly IMailDialogService _dialogService = App.Current.Services.GetRequiredService();
private readonly IAiActionOptionsService _optionsService = App.Current.Services.GetRequiredService();
+ private readonly IPreferencesService _preferencesService = App.Current.Services.GetRequiredService();
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.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;
diff --git a/Wino.Mail.WinUI/Services/PreferencesService.cs b/Wino.Mail.WinUI/Services/PreferencesService.cs
index f239003b..db216fba 100644
--- a/Wino.Mail.WinUI/Services/PreferencesService.cs
+++ b/Wino.Mail.WinUI/Services/PreferencesService.cs
@@ -389,6 +389,24 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
set => SetPropertyAndSave(nameof(IsWinoAccountButtonHidden), value);
}
+ public string AiDefaultTranslationLanguageCode
+ {
+ get => _configurationService.Get(nameof(AiDefaultTranslationLanguageCode), "en-US");
+ set => SetPropertyAndSave(nameof(AiDefaultTranslationLanguageCode), string.IsNullOrWhiteSpace(value) ? "en-US" : value.Trim());
+ }
+
+ public string AiSummarizeLanguageCode
+ {
+ get => _configurationService.Get(nameof(AiSummarizeLanguageCode), "en-US");
+ set => SetPropertyAndSave(nameof(AiSummarizeLanguageCode), string.IsNullOrWhiteSpace(value) ? "en-US" : value.Trim());
+ }
+
+ public string AiSummarySavePath
+ {
+ get => _configurationService.Get(nameof(AiSummarySavePath), string.Empty);
+ set => SetPropertyAndSave(nameof(AiSummarySavePath), value?.Trim() ?? string.Empty);
+ }
+
public WinoApplicationMode DefaultApplicationMode
{
get
diff --git a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
index 0a42de2b..6530aa27 100644
--- a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
+++ b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
@@ -7,6 +7,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:models="using:Wino.Core.Domain.Models.Ai"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:translations="using:Wino.Core.Domain.Models.Translations"
mc:Ignorable="d">
@@ -74,6 +75,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wino.Services/WinoAccountApiClient.cs b/Wino.Services/WinoAccountApiClient.cs
index 9531a032..29026a6a 100644
--- a/Wino.Services/WinoAccountApiClient.cs
+++ b/Wino.Services/WinoAccountApiClient.cs
@@ -108,11 +108,11 @@ public sealed class WinoAccountApiClient : IWinoAccountApiClient, IDisposable
public Task> GetAiStatusAsync(CancellationToken cancellationToken = default)
=> SendAuthorizedRequestAsync("api/v1/ai/status", WinoAccountApiJsonContext.Default.ApiEnvelopeAiStatusResultDto, cancellationToken);
- public Task> SummarizeAsync(string html, CancellationToken cancellationToken = default)
+ public Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default)
=> SendAuthorizedRequestAsync(
HttpMethod.Post,
"api/v1/ai/summarize",
- new SummarizeRequest(html),
+ new SummarizeRequest(html, targetLanguage),
WinoAccountApiJsonContext.Default.SummarizeRequest,
WinoAccountApiJsonContext.Default.ApiEnvelopeAiTextResultDto,
cancellationToken);
diff --git a/Wino.Services/WinoAccountProfileService.cs b/Wino.Services/WinoAccountProfileService.cs
index da662b16..d44c522b 100644
--- a/Wino.Services/WinoAccountProfileService.cs
+++ b/Wino.Services/WinoAccountProfileService.cs
@@ -213,8 +213,8 @@ public sealed class WinoAccountProfileService : BaseDatabaseService, IWinoAccoun
return response;
}
- public async Task> SummarizeAsync(string html, CancellationToken cancellationToken = default)
- => await ExecuteAiOperationAsync(account => _apiClient.SummarizeAsync(html, cancellationToken), "summarize", cancellationToken).ConfigureAwait(false);
+ public async Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default)
+ => await ExecuteAiOperationAsync(account => _apiClient.SummarizeAsync(html, targetLanguage, cancellationToken), "summarize", cancellationToken).ConfigureAwait(false);
public async Task> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default)
=> await ExecuteAiOperationAsync(account => _apiClient.TranslateAsync(html, targetLanguage, cancellationToken), "translate", cancellationToken).ConfigureAwait(false);