- Strings.cs : ~80 new keys covering status messages, progress detail (DL/extraction/verify), license summary, license details dialog, onboarding statuses, settings field labels, restart/cancel/quit confirmations, toasts, resume choice, copyright. Strings.FormatSize and Strings.FormatDate / FormatLongDate switch units (o/Ko vs B/KB) and pattern (dd/MM/yyyy vs M/d/yyyy vs 2026年) by active language. - License terminology renamed across UI: "License" → "License de mise à jour" / "Software Update License" to clarify it gates UPDATES, not Proserve itself. Expired/revoked dialogs now spell out "you can still download versions released before this date and launch any installed version". - "🔒 License insuffisante" → "🔒 License de mise à jour requise pour cette version" / "Valid update license needed for this version" so users understand it's a per-version eligibility check, not a global block. - All hardcoded FR strings in views (SettingsDialog labels, LicenseDetails fields, Onboarding statuses, dialog titles, copyright, window chrome tooltips, "Sortie le", etc.) replaced with x:Static loc bindings. - All FormatSize duplicates (5 places) and date format strings (8 places) delegate to Strings helpers — single source of truth for localization. - Settings dialog: License section moved to the top before Language. It's the most important info and conditions what the user can download. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86 lines
3.5 KiB
C#
86 lines
3.5 KiB
C#
using System.Windows;
|
|
using System.Windows.Media;
|
|
using PSLauncher.Core.Licensing;
|
|
using PSLauncher.Core.Localization;
|
|
using PSLauncher.Models;
|
|
|
|
namespace PSLauncher.App.Views;
|
|
|
|
public partial class LicenseDetailsDialog : Window
|
|
{
|
|
private readonly ILicenseService _licenseService;
|
|
private readonly LicenseValidationResponse _license;
|
|
|
|
public bool DeactivateRequested { get; private set; }
|
|
|
|
public LicenseDetailsDialog(ILicenseService licenseService, LicenseValidationResponse license)
|
|
{
|
|
_licenseService = licenseService;
|
|
_license = license;
|
|
InitializeComponent();
|
|
|
|
var (icon, title, subtitle, color, bgColor) = ResolveStyle(license);
|
|
StatusIconText.Text = icon;
|
|
StatusIconText.Foreground = new SolidColorBrush(color);
|
|
StatusTitleText.Text = title;
|
|
StatusSubtitleText.Text = subtitle;
|
|
HeaderBorder.Background = new SolidColorBrush(bgColor);
|
|
HeaderBorder.BorderBrush = new SolidColorBrush(color);
|
|
|
|
OwnerText.Text = license.OwnerName ?? "—";
|
|
UntilText.Text = license.DownloadEntitlementUntil is { } until
|
|
? Strings.FormatLongDate(until)
|
|
: "—";
|
|
IssuedText.Text = license.IssuedAt is { } issued
|
|
? Strings.FormatDate(issued)
|
|
: Strings.FormatDate(license.ServerTime);
|
|
MachineIdText.Text = licenseService.GetMachineId();
|
|
}
|
|
|
|
private static (string Icon, string Title, string Subtitle, Color Color, Color BgColor) ResolveStyle(LicenseValidationResponse l)
|
|
{
|
|
var until = l.DownloadEntitlementUntil;
|
|
if (l.Status == "valid")
|
|
{
|
|
if (until is { } u && (u - DateTime.UtcNow).TotalDays < 30)
|
|
return ("⏰", Strings.LicenseDetailsValidTitle, Strings.LicenseDetailsExpiringSoon(Strings.FormatDate(u)),
|
|
Color.FromRgb(0xF5, 0x9E, 0x0B), Color.FromRgb(0x3A, 0x2A, 0x0E));
|
|
return ("✓", Strings.LicenseDetailsValidTitle, Strings.LicenseDetailsValidSubtitle,
|
|
Color.FromRgb(0x16, 0xA3, 0x4A), Color.FromRgb(0x0E, 0x2A, 0x1B));
|
|
}
|
|
if (l.Status == "expired")
|
|
return ("⚠", Strings.LicenseDetailsExpiredTitle,
|
|
until is { } u ? Strings.LicenseDetailsExpiredSubtitle(Strings.FormatDate(u)) : Strings.LicenseDetailsExpiredFallback,
|
|
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
|
if (l.Status == "revoked")
|
|
return ("🚫", Strings.LicenseDetailsRevokedTitle, Strings.LicenseDetailsRevokedSubtitle,
|
|
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
|
return ("❓", Strings.LicenseDetailsUnknownTitle, l.Message ?? l.Status,
|
|
Color.FromRgb(0xEF, 0x44, 0x44), Color.FromRgb(0x2A, 0x14, 0x14));
|
|
}
|
|
|
|
private void OnCopyMachineId(object sender, RoutedEventArgs e)
|
|
{
|
|
try { Clipboard.SetText(MachineIdText.Text); } catch { /* ignore */ }
|
|
}
|
|
|
|
private void OnDeactivate(object sender, RoutedEventArgs e)
|
|
{
|
|
var confirm = MessageBox.Show(
|
|
Strings.MsgDeactivateLicenseDetailedConfirm,
|
|
Strings.MsgBoxConfirm,
|
|
MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
|
|
if (confirm != MessageBoxResult.Yes) return;
|
|
_licenseService.Clear();
|
|
DeactivateRequested = true;
|
|
DialogResult = true;
|
|
Close();
|
|
}
|
|
|
|
private void OnClose(object sender, RoutedEventArgs e)
|
|
{
|
|
DialogResult = false;
|
|
Close();
|
|
}
|
|
}
|