New management page.
This commit is contained in:
@@ -857,11 +857,15 @@
|
|||||||
"SettingsSearch_KeyboardShortcuts_Keywords": "shortcut;shortcuts;hotkey;hotkeys;keyboard;keys",
|
"SettingsSearch_KeyboardShortcuts_Keywords": "shortcut;shortcuts;hotkey;hotkeys;keyboard;keys",
|
||||||
"SettingsSearch_WinoAccount_Keywords": "winoaccount;account;accounts;wino",
|
"SettingsSearch_WinoAccount_Keywords": "winoaccount;account;accounts;wino",
|
||||||
"WinoAccount_Management_Description": "Manage your Wino Account, AI Pack access, and synchronized settings.",
|
"WinoAccount_Management_Description": "Manage your Wino Account, AI Pack access, and synchronized settings.",
|
||||||
"WinoAccount_Management_SignedOutTitle": "Sign in to Wino Account",
|
"WinoAccount_Management_SignedOutTitle": "Sign in to Wino Mail",
|
||||||
"WinoAccount_Management_SignedOutDescription": "Sign in or create a Wino Account to sync your settings and manage Wino add-ons.",
|
"WinoAccount_Management_SignedOutDescription": "Sign in or create an account to sync your email, access AI features, and manage your settings across devices.",
|
||||||
|
"WinoAccount_Management_ProfileSectionHeader": "Profile",
|
||||||
|
"WinoAccount_Management_AiPackSectionHeader": "AI Pack",
|
||||||
|
"WinoAccount_Management_DataSectionHeader": "Data",
|
||||||
|
"WinoAccount_Management_AccountActionsSectionHeader": "Account actions",
|
||||||
"WinoAccount_Management_AccountCardTitle": "Account",
|
"WinoAccount_Management_AccountCardTitle": "Account",
|
||||||
"WinoAccount_Management_AccountCardDescription": "Your Wino Account email address and current account state.",
|
"WinoAccount_Management_AccountCardDescription": "Your Wino Account email address and current account state.",
|
||||||
"WinoAccount_Management_AiPackCardTitle": "Wino AI Pack",
|
"WinoAccount_Management_AiPackCardTitle": "AI Pack",
|
||||||
"WinoAccount_Management_AiPackCardDescription": "See whether Wino AI Pack is active and how much usage is left.",
|
"WinoAccount_Management_AiPackCardDescription": "See whether Wino AI Pack is active and how much usage is left.",
|
||||||
"WinoAccount_Management_AiPackActive": "AI Pack is active",
|
"WinoAccount_Management_AiPackActive": "AI Pack is active",
|
||||||
"WinoAccount_Management_AiPackInactive": "AI Pack is not active",
|
"WinoAccount_Management_AiPackInactive": "AI Pack is not active",
|
||||||
@@ -869,6 +873,24 @@
|
|||||||
"WinoAccount_Management_AiPackBillingPeriod": "Billing period: {0:d} - {1:d}",
|
"WinoAccount_Management_AiPackBillingPeriod": "Billing period: {0:d} - {1:d}",
|
||||||
"WinoAccount_Management_AiPackUnknownUsage": "Usage details are not available yet.",
|
"WinoAccount_Management_AiPackUnknownUsage": "Usage details are not available yet.",
|
||||||
"WinoAccount_Management_AiPackBuyDescription": "Buy Wino AI Pack to translate, rewrite or summarize emails with AI.",
|
"WinoAccount_Management_AiPackBuyDescription": "Buy Wino AI Pack to translate, rewrite or summarize emails with AI.",
|
||||||
|
"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_AiPackGetButton": "Get AI Pack",
|
||||||
|
"WinoAccount_Management_AiPackSubscriptionActive": "Your subscription is active",
|
||||||
|
"WinoAccount_Management_AiPackRenews": "Renews {0:d}",
|
||||||
|
"WinoAccount_Management_AiPackRequestsUsed": "Requests used this month",
|
||||||
|
"WinoAccount_Management_AiPackResets": "Resets {0:d}",
|
||||||
|
"WinoAccount_Management_AiPackFeatureTranslate": "Translate",
|
||||||
|
"WinoAccount_Management_AiPackFeatureRewrite": "Rewrite",
|
||||||
|
"WinoAccount_Management_AiPackFeatureSummarize": "Summarize",
|
||||||
|
"WinoAccount_Management_ImportSettingsTitle": "Import settings",
|
||||||
|
"WinoAccount_Management_ImportSettingsDescription": "Restore your preferences from cloud.",
|
||||||
|
"WinoAccount_Management_ExportSettingsTitle": "Export settings",
|
||||||
|
"WinoAccount_Management_ExportSettingsDescription": "Save your preferences to cloud.",
|
||||||
|
"WinoAccount_Management_SignOutTitle": "Sign out",
|
||||||
|
"WinoAccount_Management_SignOutDescription": "Sign out of your account on this device",
|
||||||
"WinoAccount_Management_SettingsCardTitle": "Settings sync",
|
"WinoAccount_Management_SettingsCardTitle": "Settings sync",
|
||||||
"WinoAccount_Management_SettingsCardDescription": "Export your current settings to your Wino Account or import them back on this device.",
|
"WinoAccount_Management_SettingsCardDescription": "Export your current settings to your Wino Account or import them back on this device.",
|
||||||
"WinoAccount_Management_StatusLabel": "Status: {0}",
|
"WinoAccount_Management_StatusLabel": "Status: {0}",
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel,
|
|||||||
public partial string WinoAccountStatusText { get; set; } = string.Empty;
|
public partial string WinoAccountStatusText { get; set; } = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedFor(nameof(CanShowAiUsage))]
|
|
||||||
[NotifyPropertyChangedFor(nameof(CanShowBuyAiPack))]
|
[NotifyPropertyChangedFor(nameof(CanShowBuyAiPack))]
|
||||||
public partial bool HasAiPack { get; set; }
|
public partial bool HasAiPack { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace Wino.Core.ViewModels;
|
|||||||
public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
||||||
{
|
{
|
||||||
private const string BuyAiPackUrl = "https://example.com/wino-ai-pack";
|
private const string BuyAiPackUrl = "https://example.com/wino-ai-pack";
|
||||||
|
private const string ManageAiPackUrl = "https://example.com/wino-ai-pack/manage";
|
||||||
|
|
||||||
private readonly IWinoAccountProfileService _profileService;
|
private readonly IWinoAccountProfileService _profileService;
|
||||||
private readonly IWinoAccountApiClient _apiClient;
|
private readonly IWinoAccountApiClient _apiClient;
|
||||||
@@ -38,6 +39,12 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
[NotifyPropertyChangedFor(nameof(CanShowBuyAiPack))]
|
[NotifyPropertyChangedFor(nameof(CanShowBuyAiPack))]
|
||||||
public partial bool IsSignedIn { get; set; }
|
public partial bool IsSignedIn { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string AccountDisplayName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string AccountInitials { get; set; } = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial string AccountEmail { get; set; } = string.Empty;
|
public partial string AccountEmail { get; set; } = string.Empty;
|
||||||
|
|
||||||
@@ -58,6 +65,21 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial string AiBillingPeriodSummary { get; set; } = string.Empty;
|
public partial string AiBillingPeriodSummary { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string AiPackRenewalText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial int AiUsageCount { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial int AiUsageLimit { get; set; } = 1;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial double AiUsagePercentage { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string AiUsageResetText { get; set; } = string.Empty;
|
||||||
|
|
||||||
public bool IsSignedOut => !IsSignedIn;
|
public bool IsSignedOut => !IsSignedIn;
|
||||||
public bool CanShowAiUsage => HasAiPack;
|
public bool CanShowAiUsage => HasAiPack;
|
||||||
public bool CanShowBuyAiPack => IsSignedIn && !HasAiPack;
|
public bool CanShowBuyAiPack => IsSignedIn && !HasAiPack;
|
||||||
@@ -137,6 +159,9 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task OpenBuyPageAsync() => await _nativeAppService.LaunchUriAsync(new Uri(BuyAiPackUrl));
|
private async Task OpenBuyPageAsync() => await _nativeAppService.LaunchUriAsync(new Uri(BuyAiPackUrl));
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task ManageAiPackAsync() => await _nativeAppService.LaunchUriAsync(new Uri(ManageAiPackUrl));
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task ExportSettingsAsync()
|
private async Task ExportSettingsAsync()
|
||||||
{
|
{
|
||||||
@@ -289,6 +314,8 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
{
|
{
|
||||||
IsSignedIn = true;
|
IsSignedIn = true;
|
||||||
AccountEmail = resolvedUser.Email;
|
AccountEmail = resolvedUser.Email;
|
||||||
|
AccountDisplayName = ExtractDisplayName(resolvedUser.Email);
|
||||||
|
AccountInitials = ExtractInitials(resolvedUser.Email);
|
||||||
AccountStatusText = string.Format(Translator.WinoAccount_Management_StatusLabel, resolvedUser.AccountStatus);
|
AccountStatusText = string.Format(Translator.WinoAccount_Management_StatusLabel, resolvedUser.AccountStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -319,12 +346,19 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
await ExecuteUIThread(() =>
|
await ExecuteUIThread(() =>
|
||||||
{
|
{
|
||||||
IsSignedIn = false;
|
IsSignedIn = false;
|
||||||
|
AccountDisplayName = string.Empty;
|
||||||
|
AccountInitials = string.Empty;
|
||||||
AccountEmail = string.Empty;
|
AccountEmail = string.Empty;
|
||||||
AccountStatusText = string.Empty;
|
AccountStatusText = string.Empty;
|
||||||
HasAiPack = false;
|
HasAiPack = false;
|
||||||
AiPackStateText = Translator.WinoAccount_Management_AiPackInactive;
|
AiPackStateText = Translator.WinoAccount_Management_AiPackInactive;
|
||||||
AiUsageSummary = string.Empty;
|
AiUsageSummary = string.Empty;
|
||||||
AiBillingPeriodSummary = string.Empty;
|
AiBillingPeriodSummary = string.Empty;
|
||||||
|
AiPackRenewalText = string.Empty;
|
||||||
|
AiUsageCount = 0;
|
||||||
|
AiUsageLimit = 1;
|
||||||
|
AiUsagePercentage = 0;
|
||||||
|
AiUsageResetText = string.Empty;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,15 +392,25 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
var hasAiPack = aiStatus?.HasAiPack == true;
|
var hasAiPack = aiStatus?.HasAiPack == true;
|
||||||
var usageText = Translator.WinoAccount_Management_AiPackUnknownUsage;
|
var usageText = Translator.WinoAccount_Management_AiPackUnknownUsage;
|
||||||
var billingText = string.Empty;
|
var billingText = string.Empty;
|
||||||
|
var renewalText = string.Empty;
|
||||||
|
var usageCount = 0;
|
||||||
|
var usageLimit = 1;
|
||||||
|
var usagePercentage = 0d;
|
||||||
|
var resetText = string.Empty;
|
||||||
|
|
||||||
if (hasAiPack && aiStatus?.Used is int used && aiStatus.MonthlyLimit is int limit && aiStatus.Remaining is int remaining)
|
if (hasAiPack && aiStatus?.Used is int used && aiStatus.MonthlyLimit is int limit && aiStatus.Remaining is int remaining)
|
||||||
{
|
{
|
||||||
usageText = string.Format(Translator.WinoAccount_Management_AiPackUsage, used, limit, remaining);
|
usageText = string.Format(Translator.WinoAccount_Management_AiPackUsage, used, limit, remaining);
|
||||||
|
usageCount = used;
|
||||||
|
usageLimit = limit > 0 ? limit : 1;
|
||||||
|
usagePercentage = (double)used / usageLimit * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasAiPack && aiStatus?.CurrentPeriodStartUtc is DateTimeOffset periodStart && aiStatus.CurrentPeriodEndUtc is DateTimeOffset periodEnd)
|
if (hasAiPack && aiStatus?.CurrentPeriodStartUtc is DateTimeOffset periodStart && aiStatus.CurrentPeriodEndUtc is DateTimeOffset periodEnd)
|
||||||
{
|
{
|
||||||
billingText = string.Format(Translator.WinoAccount_Management_AiPackBillingPeriod, periodStart.LocalDateTime, periodEnd.LocalDateTime);
|
billingText = string.Format(Translator.WinoAccount_Management_AiPackBillingPeriod, periodStart.LocalDateTime, periodEnd.LocalDateTime);
|
||||||
|
renewalText = string.Format(Translator.WinoAccount_Management_AiPackRenews, periodEnd.LocalDateTime);
|
||||||
|
resetText = string.Format(Translator.WinoAccount_Management_AiPackResets, periodEnd.LocalDateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = ExecuteUIThread(() =>
|
_ = ExecuteUIThread(() =>
|
||||||
@@ -377,9 +421,36 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel
|
|||||||
: Translator.WinoAccount_Management_AiPackInactive;
|
: Translator.WinoAccount_Management_AiPackInactive;
|
||||||
AiUsageSummary = hasAiPack ? usageText : string.Empty;
|
AiUsageSummary = hasAiPack ? usageText : string.Empty;
|
||||||
AiBillingPeriodSummary = hasAiPack ? billingText : string.Empty;
|
AiBillingPeriodSummary = hasAiPack ? billingText : string.Empty;
|
||||||
|
AiPackRenewalText = hasAiPack ? renewalText : string.Empty;
|
||||||
|
AiUsageCount = usageCount;
|
||||||
|
AiUsageLimit = usageLimit;
|
||||||
|
AiUsagePercentage = usagePercentage;
|
||||||
|
AiUsageResetText = hasAiPack ? resetText : string.Empty;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ExtractDisplayName(string email)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(email))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var atIndex = email.IndexOf('@');
|
||||||
|
var localPart = atIndex > 0 ? email[..atIndex] : email;
|
||||||
|
|
||||||
|
if (localPart.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return char.ToUpper(localPart[0], CultureInfo.CurrentCulture) + localPart[1..];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractInitials(string email)
|
||||||
|
{
|
||||||
|
var displayName = ExtractDisplayName(email);
|
||||||
|
return displayName.Length > 0
|
||||||
|
? displayName[..1].ToUpper(CultureInfo.CurrentCulture)
|
||||||
|
: string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private Dictionary<string, object?> CollectPreferencesSnapshot()
|
private Dictionary<string, object?> CollectPreferencesSnapshot()
|
||||||
{
|
{
|
||||||
var settings = new Dictionary<string, object?>(StringComparer.Ordinal);
|
var settings = new Dictionary<string, object?>(StringComparer.Ordinal);
|
||||||
|
|||||||
@@ -12,12 +12,8 @@
|
|||||||
|
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
<TextBlock
|
|
||||||
Margin="0,0,0,8"
|
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{x:Bind domain:Translator.WinoAccount_Management_Description}" />
|
|
||||||
|
|
||||||
|
<!-- Busy indicator -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
x:Name="BusyPanel"
|
x:Name="BusyPanel"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
@@ -30,76 +26,296 @@
|
|||||||
<TextBlock HorizontalAlignment="Center" Text="{x:Bind domain:Translator.Busy}" />
|
<TextBlock HorizontalAlignment="Center" Text="{x:Bind domain:Translator.Busy}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════ -->
|
||||||
|
<!-- SIGNED-OUT VIEW -->
|
||||||
|
<!-- ══════════════════════════════════════ -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
x:Name="SignedOutPanel"
|
x:Name="SignedOutPanel"
|
||||||
x:Load="{x:Bind ViewModel.IsSignedOut, Mode=OneWay}"
|
x:Load="{x:Bind ViewModel.IsSignedOut, Mode=OneWay}"
|
||||||
Spacing="{StaticResource SettingsCardSpacing}">
|
Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_SignedOutDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_SignedOutTitle}">
|
|
||||||
<controls:SettingsCard.HeaderIcon>
|
<StackPanel
|
||||||
<SymbolIcon Symbol="Contact" />
|
Padding="0,40,0,40"
|
||||||
</controls:SettingsCard.HeaderIcon>
|
HorizontalAlignment="Center"
|
||||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
Spacing="16">
|
||||||
|
|
||||||
|
<!-- App logo -->
|
||||||
|
<Image
|
||||||
|
Width="64"
|
||||||
|
Height="64"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Source="ms-appx:///Assets/AppEntries/MailAssets/Square150x150Logo.scale-100.png" />
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontSize="20"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_SignedOutTitle}" />
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<TextBlock
|
||||||
|
MaxWidth="360"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_SignedOutDescription}"
|
||||||
|
TextAlignment="Center"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
|
||||||
|
<!-- Action buttons -->
|
||||||
|
<StackPanel
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Spacing="12">
|
||||||
|
<Button
|
||||||
|
Command="{x:Bind ViewModel.SignInCommand}"
|
||||||
|
Content="{x:Bind domain:Translator.Buttons_SignIn}"
|
||||||
|
Style="{StaticResource AccentButtonStyle}" />
|
||||||
<Button Command="{x:Bind ViewModel.RegisterCommand}" Content="{x:Bind domain:Translator.Buttons_CreateAccount}" />
|
<Button Command="{x:Bind ViewModel.RegisterCommand}" Content="{x:Bind domain:Translator.Buttons_CreateAccount}" />
|
||||||
<Button Command="{x:Bind ViewModel.SignInCommand}" Content="{x:Bind domain:Translator.Buttons_SignIn}" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</controls:SettingsCard>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════ -->
|
||||||
|
<!-- SIGNED-IN VIEW -->
|
||||||
|
<!-- ══════════════════════════════════════ -->
|
||||||
<StackPanel
|
<StackPanel
|
||||||
x:Name="SignedInPanel"
|
x:Name="SignedInPanel"
|
||||||
x:Load="{x:Bind ViewModel.IsSignedIn, Mode=OneWay}"
|
x:Load="{x:Bind ViewModel.IsSignedIn, Mode=OneWay}"
|
||||||
Spacing="{StaticResource SettingsCardSpacing}">
|
Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_AccountCardDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_AccountCardTitle}">
|
|
||||||
<controls:SettingsCard.HeaderIcon>
|
<!-- ─── Profile section ─── -->
|
||||||
<SymbolIcon Symbol="Contact" />
|
<TextBlock
|
||||||
</controls:SettingsCard.HeaderIcon>
|
Margin="0,0,0,4"
|
||||||
<StackPanel Spacing="8">
|
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||||
<TextBlock FontWeight="SemiBold" Text="{x:Bind ViewModel.AccountEmail, Mode=OneWay}" />
|
Text="{x:Bind domain:Translator.WinoAccount_Management_ProfileSectionHeader}" />
|
||||||
<TextBlock Text="{x:Bind ViewModel.AccountStatusText, Mode=OneWay}" />
|
|
||||||
<Button
|
<controls:SettingsCard>
|
||||||
HorizontalAlignment="Left"
|
<controls:SettingsCard.Header>
|
||||||
Command="{x:Bind ViewModel.SignOutCommand}"
|
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||||
Content="{x:Bind domain:Translator.WinoAccount_SignOutButton_Action}" />
|
<PersonPicture
|
||||||
</StackPanel>
|
Width="40"
|
||||||
|
Height="40"
|
||||||
|
Initials="{x:Bind ViewModel.AccountInitials, Mode=OneWay}" />
|
||||||
|
<StackPanel VerticalAlignment="Center" Spacing="2">
|
||||||
|
<TextBlock FontWeight="SemiBold" Text="{x:Bind ViewModel.AccountDisplayName, Mode=OneWay}" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.AccountEmail, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingsCard.Header>
|
||||||
|
<Border
|
||||||
|
Padding="12,4"
|
||||||
|
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
|
||||||
|
CornerRadius="12">
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource SystemFillColorSuccessBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.AccountStatusText, Mode=OneWay}" />
|
||||||
|
</Border>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_AiPackCardDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_AiPackCardTitle}">
|
<!-- ─── AI Pack section ─── -->
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,12,0,4"
|
||||||
|
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackSectionHeader}" />
|
||||||
|
|
||||||
<StackPanel Spacing="8">
|
<!-- AI Pack promo (no AI Pack) -->
|
||||||
<TextBlock FontWeight="SemiBold" Text="{x:Bind ViewModel.AiPackStateText, Mode=OneWay}" />
|
<controls:SettingsCard
|
||||||
<TextBlock
|
x:Name="AiPackPromoCard"
|
||||||
x:Name="CanShowAITextBlock"
|
x:Load="{x:Bind ViewModel.CanShowBuyAiPack, Mode=OneWay}"
|
||||||
x:Load="{x:Bind ViewModel.CanShowAiUsage, Mode=OneWay}"
|
Description="{x:Bind domain:Translator.WinoAccount_Management_AiPackPromoDescription}">
|
||||||
Text="{x:Bind ViewModel.AiUsageSummary, Mode=OneWay}"
|
<controls:SettingsCard.HeaderIcon>
|
||||||
TextWrapping="WrapWholeWords" />
|
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||||
<TextBlock
|
</controls:SettingsCard.HeaderIcon>
|
||||||
x:Name="BillingBlock"
|
<controls:SettingsCard.Header>
|
||||||
x:Load="{x:Bind ViewModel.CanShowAiUsage, Mode=OneWay}"
|
<StackPanel Spacing="8">
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
Text="{x:Bind ViewModel.AiBillingPeriodSummary, Mode=OneWay}"
|
<TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackPromoTitle}" />
|
||||||
TextWrapping="WrapWholeWords" />
|
<Border
|
||||||
<TextBlock
|
Padding="8,2"
|
||||||
x:Name="CanBuyAIPack"
|
Background="{ThemeResource SystemAccentColor}"
|
||||||
x:Load="{x:Bind ViewModel.CanShowBuyAiPack, Mode=OneWay}"
|
CornerRadius="4">
|
||||||
Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackBuyDescription}"
|
<TextBlock
|
||||||
TextWrapping="WrapWholeWords" />
|
FontSize="10"
|
||||||
<Button
|
FontWeight="Bold"
|
||||||
x:Name="OpenBuyPageButton"
|
Foreground="White"
|
||||||
HorizontalAlignment="Left"
|
Text="PRO" />
|
||||||
x:Load="{x:Bind ViewModel.CanShowBuyAiPack, Mode=OneWay}"
|
</Border>
|
||||||
Command="{x:Bind ViewModel.OpenBuyPageCommand}"
|
</StackPanel>
|
||||||
Content="{x:Bind domain:Translator.Buttons_Purchase}" />
|
<TextBlock
|
||||||
</StackPanel>
|
MaxWidth="400"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackPromoDescription}"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="16">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||||
|
<FontIcon
|
||||||
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Glyph="" />
|
||||||
|
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureTranslate}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||||
|
<FontIcon
|
||||||
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Glyph="" />
|
||||||
|
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureRewrite}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||||
|
<FontIcon
|
||||||
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Glyph="" />
|
||||||
|
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackFeatureSummarize}" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Margin="0,4,0,0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Spacing="12">
|
||||||
|
<Button
|
||||||
|
Command="{x:Bind ViewModel.OpenBuyPageCommand}"
|
||||||
|
Content="{x:Bind domain:Translator.WinoAccount_Management_AiPackGetButton}"
|
||||||
|
Style="{StaticResource AccentButtonStyle}" />
|
||||||
|
<TextBlock
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}">
|
||||||
|
<Run Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackPromoPrice}" />
|
||||||
|
<Run Text=" · " />
|
||||||
|
<Run Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackPromoRequests}" />
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingsCard.Header>
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
|
||||||
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_SettingsCardDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_SettingsCardTitle}">
|
<!-- AI Pack active: subscription info -->
|
||||||
|
<controls:SettingsExpander
|
||||||
|
x:Name="AiPackActiveCard"
|
||||||
|
x:Load="{x:Bind ViewModel.HasAiPack, Mode=OneWay}"
|
||||||
|
IsExpanded="True">
|
||||||
|
<controls:SettingsExpander.HeaderIcon>
|
||||||
|
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||||
|
</controls:SettingsExpander.HeaderIcon>
|
||||||
|
<controls:SettingsExpander.Header>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackCardTitle}" />
|
||||||
|
<Border
|
||||||
|
Padding="8,2"
|
||||||
|
Background="{ThemeResource SystemAccentColor}"
|
||||||
|
CornerRadius="4">
|
||||||
|
<TextBlock
|
||||||
|
FontSize="10"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="White"
|
||||||
|
Text="PRO" />
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingsExpander.Header>
|
||||||
|
<controls:SettingsExpander.Description>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackSubscriptionActive}" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text=" · " />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.AiPackRenewalText, Mode=OneWay}" />
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingsExpander.Description>
|
||||||
|
<HyperlinkButton Command="{x:Bind ViewModel.ManageAiPackCommand}" Content="{x:Bind domain:Translator.Buttons_Manage}" />
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
|
||||||
|
<!-- AI Pack active: usage bar -->
|
||||||
|
|
||||||
|
<controls:SettingsCard x:Name="AiPackUsageCard" HorizontalContentAlignment="Stretch">
|
||||||
|
<controls:SettingsCard.Header>
|
||||||
|
<StackPanel MinWidth="400" Spacing="8">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||||
|
<TextBlock
|
||||||
|
FontSize="24"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Text="{x:Bind ViewModel.AiUsageCount, Mode=OneWay}" />
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,0,0,2"
|
||||||
|
VerticalAlignment="Bottom"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}">
|
||||||
|
<Run Text="/ " />
|
||||||
|
<Run Text="{x:Bind ViewModel.AiUsageLimit, Mode=OneWay}" />
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<ProgressBar
|
||||||
|
Height="8"
|
||||||
|
Maximum="100"
|
||||||
|
Value="{x:Bind ViewModel.AiUsagePercentage, Mode=OneWay}" />
|
||||||
|
<Grid>
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_AiPackRequestsUsed}" />
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.AiUsageResetText, Mode=OneWay}" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingsCard.Header>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ─── Data section ─── -->
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,12,0,4"
|
||||||
|
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_DataSectionHeader}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_ImportSettingsDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_ImportSettingsTitle}">
|
||||||
<controls:SettingsCard.HeaderIcon>
|
<controls:SettingsCard.HeaderIcon>
|
||||||
<SymbolIcon Symbol="Sync" />
|
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||||
|
</controls:SettingsCard.HeaderIcon>
|
||||||
|
<Button Command="{x:Bind ViewModel.ImportSettingsCommand}" Content="{x:Bind domain:Translator.Buttons_Browse}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<controls:SettingsCard Description="{x:Bind domain:Translator.WinoAccount_Management_ExportSettingsDescription}" Header="{x:Bind domain:Translator.WinoAccount_Management_ExportSettingsTitle}">
|
||||||
|
<controls:SettingsCard.HeaderIcon>
|
||||||
|
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||||
|
</controls:SettingsCard.HeaderIcon>
|
||||||
|
<Button Command="{x:Bind ViewModel.ExportSettingsCommand}" Content="{x:Bind domain:Translator.Buttons_Export}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
|
||||||
|
<!-- ─── Account actions section ─── -->
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,12,0,4"
|
||||||
|
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.WinoAccount_Management_AccountActionsSectionHeader}" />
|
||||||
|
|
||||||
|
<controls:SettingsCard
|
||||||
|
Command="{x:Bind ViewModel.SignOutCommand}"
|
||||||
|
Description="{x:Bind domain:Translator.WinoAccount_Management_SignOutDescription}"
|
||||||
|
Header="{x:Bind domain:Translator.WinoAccount_Management_SignOutTitle}"
|
||||||
|
IsClickEnabled="True">
|
||||||
|
<controls:SettingsCard.HeaderIcon>
|
||||||
|
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" />
|
||||||
</controls:SettingsCard.HeaderIcon>
|
</controls:SettingsCard.HeaderIcon>
|
||||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
|
||||||
<Button Command="{x:Bind ViewModel.ExportSettingsCommand}" Content="{x:Bind domain:Translator.Buttons_Export}" />
|
|
||||||
<Button Command="{x:Bind ViewModel.ImportSettingsCommand}" Content="{x:Bind domain:Translator.Buttons_Import}" />
|
|
||||||
</StackPanel>
|
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
Reference in New Issue
Block a user