Browse Source

Resending works

Krzysztof Krysiński 4 months ago
parent
commit
9bd6e9d96d

+ 14 - 1
src/PixiEditor.PixiAuth/PixiAuthClient.cs

@@ -1,6 +1,7 @@
 using System.Net;
 using System.Net.Http.Headers;
 using System.Net.Http.Json;
+using System.Text.Json;
 using PixiEditor.PixiAuth.Exceptions;
 
 namespace PixiEditor.PixiAuth;
@@ -167,13 +168,25 @@ public class PixiAuthClient
                     await response.Content.ReadAsStringAsync());
             if (responseData != null && responseData.TryGetValue("error", out object? error))
             {
+                if (error is JsonElement errorElement)
+                {
+                    error = errorElement.GetString();
+                }
+
+
                 if (error is string errorString and "TOO_MANY_REQUESTS")
                 {
                     if (responseData.TryGetValue("timeLeft", out object? timeLeft))
                     {
+                        if (timeLeft is JsonElement timeLeftElement)
+                        {
+                            timeLeft = timeLeftElement.GetDouble();
+                        }
+
                         if (timeLeft is double timeLeftDouble)
                         {
-                            throw new TooManyRequestsException(errorString, timeLeftDouble);
+                            double seconds = double.Round(timeLeftDouble / 1000);
+                            throw new TooManyRequestsException(errorString, seconds);
                         }
                     }
 

+ 1 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1030,5 +1030,5 @@
   "SESSION_NOT_VALID": "Session is not valid, please log in again",
   "SESSION_NOT_FOUND": "Session not found, try logging in again",
   "INTERNAL_SERVER_ERROR": "There was an internal server error. Please try again later.",
-  "TOO_MANY_REQUESTS": "Too many requests. Try again in {0}"
+  "TOO_MANY_REQUESTS": "Too many requests. Try again in {0} seconds."
 }

+ 46 - 3
src/PixiEditor/ViewModels/SubViewModels/UserViewModel.cs

@@ -1,3 +1,4 @@
+using Avalonia.Threading;
 using CommunityToolkit.Mvvm.Input;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -30,6 +31,22 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
 
     private bool apiValid = true;
 
+    public DateTime? TimeToEndTimeout { get; private set; } = null;
+
+    public string TimeToEndTimeoutString
+    {
+        get
+        {
+            if (TimeToEndTimeout == null)
+            {
+                return string.Empty;
+            }
+
+            TimeSpan timeLeft = TimeToEndTimeout.Value - DateTime.Now;
+            return timeLeft.TotalSeconds > 0 ? $"({timeLeft:ss})" : string.Empty;
+        }
+    }
+
     public UserViewModel(ViewModelMain owner) : base(owner)
     {
         RequestLoginCommand = new AsyncRelayCommand<string>(RequestLogin);
@@ -65,7 +82,6 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
         });
     }
 
-
     public async Task RequestLogin(string email)
     {
         if (!apiValid) return;
@@ -83,7 +99,7 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
         }
         catch (PixiAuthException authException)
         {
-           LastError = new LocalizedString(authException.Message);
+            LastError = new LocalizedString(authException.Message);
         }
     }
 
@@ -99,11 +115,17 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
         try
         {
             await PixiAuthClient.ResendActivation(User.Email, User.SessionId.Value);
+            TimeToEndTimeout = DateTime.Now.Add(TimeSpan.FromSeconds(60));
+            RunTimeoutTimers(60);
+            NotifyProperties();
             LastError = null;
         }
         catch (TooManyRequestsException e)
         {
             LastError = new LocalizedString(e.Message, e.TimeLeft);
+            TimeToEndTimeout = DateTime.Now.Add(TimeSpan.FromSeconds(e.TimeLeft));
+            RunTimeoutTimers(e.TimeLeft);
+            NotifyProperties();
         }
         catch (PixiAuthException authException)
         {
@@ -111,9 +133,26 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
         }
     }
 
+    private void RunTimeoutTimers(double timeLeft)
+    {
+        DispatcherTimer.RunOnce(
+            () =>
+            {
+                TimeToEndTimeout = null;
+                NotifyProperties();
+            },
+            TimeSpan.FromSeconds(timeLeft));
+
+        DispatcherTimer.Run(() =>
+        {
+            NotifyProperties();
+            return TimeToEndTimeout != null;
+        }, TimeSpan.FromSeconds(1));
+    }
+
     public bool CanResendActivation()
     {
-        return WaitingForActivation;
+        return WaitingForActivation && TimeToEndTimeout == null;
     }
 
     public async Task<bool> TryRefreshToken()
@@ -219,5 +258,9 @@ internal class UserViewModel : SubViewModel<ViewModelMain>
         OnPropertyChanged(nameof(NotLoggedIn));
         OnPropertyChanged(nameof(WaitingForActivation));
         OnPropertyChanged(nameof(IsLoggedIn));
+        OnPropertyChanged(nameof(LastError));
+        OnPropertyChanged(nameof(TimeToEndTimeout));
+        OnPropertyChanged(nameof(TimeToEndTimeoutString));
+        ResendActivationCommand.NotifyCanExecuteChanged();
     }
 }

+ 5 - 2
src/PixiEditor/Views/Auth/LoginPopup.axaml

@@ -20,8 +20,11 @@
         <TextBlock Text="Logged in as " IsVisible="{Binding IsLoggedIn}">
             <Run Text="{Binding User.Email}" />
         </TextBlock>
-        <Button IsVisible="{Binding WaitingForActivation}"
-                Command="{Binding Path=ResendActivationCommand}" Content="Resend" HorizontalAlignment="Right">
+        <Button IsVisible="{Binding WaitingForActivation}" Width="100"
+                Command="{Binding Path=ResendActivationCommand}" HorizontalAlignment="Right">
+            <TextBlock Text="Resend" Width="100">
+                <TextBlock Text="{Binding TimeToEndTimeoutString}"/>
+            </TextBlock>
         </Button>
         <Button IsVisible="{Binding IsLoggedIn}"
                 Command="{Binding Path=LogoutCommand}" Content="Logout" HorizontalAlignment="Right" />