using IronLicensing.Client; using IronLicensing.Client.Models; namespace IronServices.Maui.Controls; /// /// A reusable license activation view for IronLicensing. /// public partial class LicenseActivationView : ContentView { private ILicenseManager? _licenseManager; public LicenseActivationView() { InitializeComponent(); } #region Bindable Properties /// /// The ILicenseManager to use for license validation. /// public static readonly BindableProperty LicenseManagerProperty = BindableProperty.Create( nameof(LicenseManager), typeof(ILicenseManager), typeof(LicenseActivationView), null, propertyChanged: (b, o, n) => ((LicenseActivationView)b)._licenseManager = n as ILicenseManager); public ILicenseManager? LicenseManager { get => (ILicenseManager?)GetValue(LicenseManagerProperty); set => SetValue(LicenseManagerProperty, value); } /// /// The title text. /// public static readonly BindableProperty TitleProperty = BindableProperty.Create( nameof(Title), typeof(string), typeof(LicenseActivationView), "Activate License", propertyChanged: (b, o, n) => ((LicenseActivationView)b).TitleLabel.Text = n as string); public string Title { get => (string)GetValue(TitleProperty); set => SetValue(TitleProperty, value); } /// /// The subtitle text. /// public static readonly BindableProperty SubtitleProperty = BindableProperty.Create( nameof(Subtitle), typeof(string), typeof(LicenseActivationView), "Enter your license key to activate", propertyChanged: (b, o, n) => ((LicenseActivationView)b).SubtitleLabel.Text = n as string); public string Subtitle { get => (string)GetValue(SubtitleProperty); set => SetValue(SubtitleProperty, value); } /// /// Pre-filled license key. /// public static readonly BindableProperty LicenseKeyProperty = BindableProperty.Create( nameof(LicenseKey), typeof(string), typeof(LicenseActivationView), null, BindingMode.TwoWay, propertyChanged: (b, o, n) => ((LicenseActivationView)b).LicenseKeyEntry.Text = n as string); public string? LicenseKey { get => (string?)GetValue(LicenseKeyProperty); set => SetValue(LicenseKeyProperty, value); } /// /// Whether to show the help link. /// public static readonly BindableProperty ShowHelpLinkProperty = BindableProperty.Create( nameof(ShowHelpLink), typeof(bool), typeof(LicenseActivationView), true, propertyChanged: (b, o, n) => ((LicenseActivationView)b).HelpLink.IsVisible = (bool)n); public bool ShowHelpLink { get => (bool)GetValue(ShowHelpLinkProperty); set => SetValue(ShowHelpLinkProperty, value); } /// /// URL to open when help link is tapped. /// public static readonly BindableProperty HelpUrlProperty = BindableProperty.Create( nameof(HelpUrl), typeof(string), typeof(LicenseActivationView), "https://ironservices.io/docs/licensing"); public string HelpUrl { get => (string)GetValue(HelpUrlProperty); set => SetValue(HelpUrlProperty, value); } #endregion #region Events /// /// Raised when license activation is successful. /// public event EventHandler? LicenseActivated; /// /// Raised when license activation fails. /// public event EventHandler? ActivationFailed; /// /// Raised when help link is tapped. /// public event EventHandler? HelpRequested; #endregion #region Event Handlers private async void OnActivateClicked(object sender, EventArgs e) { if (_licenseManager == null) { ShowError("License manager not configured"); return; } var licenseKey = LicenseKeyEntry.Text?.Trim(); if (string.IsNullOrEmpty(licenseKey)) { ShowError("Please enter a license key"); return; } SetLoading(true); HideError(); HideStatus(); try { var result = await _licenseManager.ActivateAsync(licenseKey); if (result.Success) { ShowStatus(true, "License activated successfully!"); LicenseActivated?.Invoke(this, new LicenseActivatedEventArgs(result)); } else { ShowError(result.ErrorMessage ?? "Invalid license key"); ActivationFailed?.Invoke(this, new LicenseActivationFailedEventArgs(result.ErrorMessage ?? "Invalid license key")); } } catch (Exception ex) { ShowError($"Error: {ex.Message}"); ActivationFailed?.Invoke(this, new LicenseActivationFailedEventArgs(ex.Message)); } finally { SetLoading(false); } } private async void OnHelpTapped(object sender, EventArgs e) { HelpRequested?.Invoke(this, EventArgs.Empty); try { await Browser.OpenAsync(HelpUrl, BrowserLaunchMode.SystemPreferred); } catch { // Ignore if can't open browser } } #endregion #region Helper Methods private void SetLoading(bool isLoading) { ActivateButton.IsEnabled = !isLoading; ActivateButton.IsVisible = !isLoading; LoadingIndicator.IsRunning = isLoading; LoadingIndicator.IsVisible = isLoading; LicenseKeyEntry.IsEnabled = !isLoading; } private void ShowError(string message) { ErrorLabel.Text = message; ErrorLabel.IsVisible = true; } private void HideError() { ErrorLabel.IsVisible = false; } private void ShowStatus(bool success, string message) { StatusFrame.IsVisible = true; StatusFrame.BackgroundColor = success ? Color.FromArgb("#D1FAE5") // Green background : Color.FromArgb("#FEE2E2"); // Red background StatusIcon.Text = success ? "✓" : "✗"; StatusIcon.TextColor = success ? Colors.Green : Colors.Red; StatusLabel.Text = message; StatusLabel.TextColor = success ? Colors.Green : Colors.Red; } private void HideStatus() { StatusFrame.IsVisible = false; } /// /// Validates the current license without activating a new one. /// public async Task ValidateAsync() { if (_licenseManager == null) return false; var licenseKey = LicenseKeyEntry.Text?.Trim(); try { var result = await _licenseManager.ValidateAsync(licenseKey); return result.Success; } catch { return false; } } #endregion } /// /// Event args for successful license activation. /// public class LicenseActivatedEventArgs : EventArgs { public LicenseResult Result { get; } public LicenseInfo? License => Result.License; public LicenseActivatedEventArgs(LicenseResult result) { Result = result; } } /// /// Event args for failed license activation. /// public class LicenseActivationFailedEventArgs : EventArgs { public string Error { get; } public LicenseActivationFailedEventArgs(string error) { Error = error; } }