Skip to content

Commit 1512a37

Browse files
committed
Add ConnectedServiceManager
1 parent 70e7f85 commit 1512a37

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.ComponentModel;
2+
using FluentAvalonia.UI.Controls;
3+
using Injectio.Attributes;
4+
using Microsoft.Extensions.Logging;
5+
using OpenIddict.Client;
6+
using StabilityMatrix.Avalonia.Languages;
7+
using StabilityMatrix.Avalonia.ViewModels.Base;
8+
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
9+
using StabilityMatrix.Core.Api;
10+
using StabilityMatrix.Core.Models.Api.Lykos;
11+
using StabilityMatrix.Core.Services;
12+
13+
namespace StabilityMatrix.Avalonia.Services;
14+
15+
[Localizable(false)]
16+
[RegisterSingleton<IConnectedServiceManager>]
17+
public class ConnectedServiceManager(
18+
IAccountsService accountsService,
19+
ISettingsManager settingsManager,
20+
ServiceManager<ViewModelBase> vmFactory,
21+
ILogger<ConnectedServiceManager> logger
22+
) : IConnectedServiceManager
23+
{
24+
/// <summary>
25+
/// Attempt to enable CivitUseDiscoveryApi, prompting for login as needed.
26+
/// </summary>
27+
public async Task<bool> PromptEnableCivitUseDiscoveryApi()
28+
{
29+
// Ensure logged in
30+
if (!await PromptLoginIfRequired() || accountsService.LykosStatus is not { User: { } user } status)
31+
{
32+
return false;
33+
}
34+
35+
// Check if we can enable
36+
var canEnable = user.Permissions.Contains("read:discovery");
37+
if (!canEnable)
38+
{
39+
logger.LogDebug("User {Id} does not have permissions: {Permissions}", user.Id, user.Permissions);
40+
41+
// Sponsor prompt
42+
var sponsorVm = vmFactory.Get<SponsorshipPromptViewModel>();
43+
sponsorVm.Initialize(status, "Accelerated Model Discovery", "Insider");
44+
await sponsorVm.ShowDialogAsync();
45+
46+
return false;
47+
}
48+
49+
logger.LogInformation("Enabling CivitUseDiscoveryApi");
50+
51+
// Save settings
52+
settingsManager.Transaction(s => s.CivitUseDiscoveryApi, true);
53+
return true;
54+
}
55+
56+
/// <summary>
57+
/// Prompts the user to log in to their Lykos account if they are not already logged in.
58+
/// </summary>
59+
/// <returns>True if the user is logged in after this function, false otherwise.</returns>
60+
public async Task<bool> PromptLoginIfRequired()
61+
{
62+
Exception? refreshException = null;
63+
64+
// Check already logged in
65+
if (accountsService.LykosStatus?.IsConnected == true)
66+
{
67+
return true;
68+
}
69+
70+
var hasStoredAccount = await accountsService.HasStoredLykosAccountAsync();
71+
72+
if (hasStoredAccount)
73+
{
74+
// Try refresh
75+
try
76+
{
77+
await accountsService.RefreshLykosAsync();
78+
}
79+
catch (Exception e)
80+
{
81+
logger.LogWarning(e, "Error refreshing Lykos account");
82+
refreshException = e;
83+
}
84+
85+
// Check again
86+
if (accountsService.LykosStatus?.IsConnected == true)
87+
{
88+
return true;
89+
}
90+
}
91+
92+
// If we have a stored account but refresh failed
93+
var isSessionExpired = hasStoredAccount && refreshException is not null;
94+
95+
var dialog = DialogHelper.CreateTaskDialog(
96+
isSessionExpired ? Resources.Text_Login_ExpiredTitle : Resources.Text_Login_ConnectTitle,
97+
isSessionExpired
98+
? Resources.Text_Login_ExpiredDescription
99+
: Resources.Text_Login_ConnectDescription
100+
);
101+
102+
dialog.Buttons =
103+
[
104+
new TaskDialogButton(Resources.Action_Login, TaskDialogStandardResult.OK) { IsDefault = true },
105+
new TaskDialogButton(Resources.Action_Close, TaskDialogStandardResult.Close),
106+
];
107+
108+
if (await dialog.ShowAsync(true) is not TaskDialogStandardResult.OK)
109+
return false;
110+
111+
var vm = vmFactory.Get<OAuthDeviceAuthViewModel>();
112+
vm.ChallengeRequest = new OpenIddictClientModels.DeviceChallengeRequest
113+
{
114+
ProviderName = OpenIdClientConstants.LykosAccount.ProviderName
115+
};
116+
await vm.ShowDialogAsync();
117+
118+
if (vm.AuthenticationResult is not { } result)
119+
return false;
120+
121+
await accountsService.LykosAccountV2LoginAsync(
122+
new LykosAccountV2Tokens(result.AccessToken, result.RefreshToken, result.IdentityToken)
123+
);
124+
125+
return true;
126+
}
127+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace StabilityMatrix.Avalonia.Services;
2+
3+
public interface IConnectedServiceManager
4+
{
5+
/// <summary>
6+
/// Attempt to enable CivitUseDiscoveryApi, prompting for login as needed.
7+
/// </summary>
8+
Task<bool> PromptEnableCivitUseDiscoveryApi();
9+
10+
/// <summary>
11+
/// Prompts the user to log in to their Lykos account if they are not already logged in.
12+
/// </summary>
13+
/// <returns>True if the user is logged in after this function, false otherwise.</returns>
14+
Task<bool> PromptLoginIfRequired();
15+
}

0 commit comments

Comments
 (0)