Merge pull request #2218 from peppy/api-as-component

Consolidate API into its own component
This commit is contained in:
Dan Balasescu
2018-03-16 15:38:17 +09:00
committed by GitHub
8 changed files with 47 additions and 66 deletions

View File

@ -8,15 +8,17 @@ using System.Diagnostics;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Threading; using osu.Game.Configuration;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
public class APIAccess : IAPIProvider public class APIAccess : Component, IAPIProvider
{ {
private readonly OsuConfigManager config;
private readonly OAuth authentication; private readonly OAuth authentication;
public string Endpoint = @"https://osu.ppy.sh"; public string Endpoint = @"https://osu.ppy.sh";
@ -25,13 +27,12 @@ namespace osu.Game.Online.API
private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>(); private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>();
public Scheduler Scheduler = new Scheduler(); /// <summary>
/// The username/email provided by the user when initiating a login.
/// </summary>
public string ProvidedUsername { get; private set; }
public string Username; private string password;
//private SecurePassword password;
public string Password;
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser()); public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
@ -41,24 +42,31 @@ namespace osu.Game.Online.API
set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); } set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); }
} }
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password); protected bool HasLogin => Token != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password);
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference). // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference).
private readonly Thread thread; private readonly Thread thread;
private readonly Logger log; private readonly Logger log;
public APIAccess() public APIAccess(OsuConfigManager config)
{ {
this.config = config;
authentication = new OAuth(client_id, client_secret, Endpoint); authentication = new OAuth(client_id, client_secret, Endpoint);
log = Logger.GetLogger(LoggingTarget.Network); log = Logger.GetLogger(LoggingTarget.Network);
ProvidedUsername = config.Get<string>(OsuSetting.Username);
Token = config.Get<string>(OsuSetting.Token);
thread = new Thread(run) { IsBackground = true }; thread = new Thread(run) { IsBackground = true };
thread.Start(); thread.Start();
} }
private readonly List<IOnlineComponent> components = new List<IOnlineComponent>(); private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
internal void Schedule(Action action) => base.Schedule(action);
public void Register(IOnlineComponent component) public void Register(IOnlineComponent component)
{ {
Scheduler.Add(delegate Scheduler.Add(delegate
@ -111,12 +119,15 @@ namespace osu.Game.Online.API
State = APIState.Connecting; State = APIState.Connecting;
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password)) // save the username at this point, if the user requested for it to be.
config.Set(OsuSetting.Username, config.Get<bool>(OsuSetting.SaveUsername) ? ProvidedUsername : string.Empty);
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(ProvidedUsername, password))
{ {
//todo: this fails even on network-related issues. we should probably handle those differently. //todo: this fails even on network-related issues. we should probably handle those differently.
//NotificationOverlay.ShowMessage("Login failed!"); //NotificationOverlay.ShowMessage("Login failed!");
log.Add(@"Login failed!"); log.Add(@"Login failed!");
Password = null; password = null;
authentication.Clear(); authentication.Clear();
continue; continue;
} }
@ -173,8 +184,8 @@ namespace osu.Game.Online.API
{ {
Debug.Assert(State == APIState.Offline); Debug.Assert(State == APIState.Offline);
Username = username; ProvidedUsername = username;
Password = password; this.password = password;
} }
/// <summary> /// <summary>
@ -283,8 +294,8 @@ namespace osu.Game.Online.API
public void Logout(bool clearUsername = true) public void Logout(bool clearUsername = true)
{ {
flushQueue(); flushQueue();
if (clearUsername) Username = null; if (clearUsername) ProvidedUsername = null;
Password = null; password = null;
authentication.Clear(); authentication.Clear();
LocalUser.Value = createGuestUser(); LocalUser.Value = createGuestUser();
} }
@ -295,9 +306,12 @@ namespace osu.Game.Online.API
Id = 1, Id = 1,
}; };
public void Update() protected override void Dispose(bool isDisposing)
{ {
Scheduler.Update(); base.Dispose(isDisposing);
config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? Token : string.Empty);
config.Save();
} }
} }

View File

@ -14,7 +14,7 @@ namespace osu.Game.Online.API
return request; return request;
} }
private void request_Progress(long current, long total) => API.Scheduler.Add(delegate { Progress?.Invoke(current, total); }); private void request_Progress(long current, long total) => API.Schedule(() => Progress?.Invoke(current, total));
protected APIDownloadRequest() protected APIDownloadRequest()
{ {

View File

@ -85,7 +85,7 @@ namespace osu.Game.Online.API
if (checkAndProcessFailure()) if (checkAndProcessFailure())
return; return;
api.Scheduler.Add(delegate { Success?.Invoke(); }); api.Schedule(delegate { Success?.Invoke(); });
} }
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled")); public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
@ -108,7 +108,7 @@ namespace osu.Game.Online.API
{ {
if (API == null || pendingFailure == null) return cancelled; if (API == null || pendingFailure == null) return cancelled;
API.Scheduler.Add(pendingFailure); API.Schedule(pendingFailure);
pendingFailure = null; pendingFailure = null;
return true; return true;
} }

View File

@ -1,13 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
public interface IAPIProvider : IUpdateable public interface IAPIProvider
{ {
/// <summary> /// <summary>
/// The local user. /// The local user.

View File

@ -34,7 +34,7 @@ using osu.Game.Skinning;
namespace osu.Game namespace osu.Game
{ {
public class OsuGameBase : Framework.Game, IOnlineComponent, ICanAcceptFiles public class OsuGameBase : Framework.Game, ICanAcceptFiles
{ {
protected OsuConfigManager LocalConfig; protected OsuConfigManager LocalConfig;
@ -56,8 +56,6 @@ namespace osu.Game
protected override string MainResourceFile => @"osu.Game.Resources.dll"; protected override string MainResourceFile => @"osu.Game.Resources.dll";
public APIAccess API;
private Container content; private Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
@ -108,16 +106,14 @@ namespace osu.Game
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
dependencies.Cache(API = new APIAccess var api = new APIAccess(LocalConfig);
{
Username = LocalConfig.Get<string>(OsuSetting.Username), dependencies.Cache(api);
Token = LocalConfig.Get<string>(OsuSetting.Token) dependencies.CacheAs<IAPIProvider>(api);
});
dependencies.CacheAs<IAPIProvider>(API);
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Host)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Host));
dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore));
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
@ -183,9 +179,9 @@ namespace osu.Game
lastBeatmap = b; lastBeatmap = b;
}; };
API.Register(this);
FileStore.Cleanup(); FileStore.Cleanup();
AddInternal(api);
} }
private void runMigrations() private void runMigrations()
@ -211,16 +207,6 @@ namespace osu.Game
private WorkingBeatmap lastBeatmap; private WorkingBeatmap lastBeatmap;
public void APIStateChanged(APIAccess api, APIState state)
{
switch (state)
{
case APIState.Online:
LocalConfig.Set(OsuSetting.Username, LocalConfig.Get<bool>(OsuSetting.SaveUsername) ? API.Username : string.Empty);
break;
}
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
@ -253,24 +239,6 @@ namespace osu.Game
base.SetHost(host); base.SetHost(host);
} }
protected override void Update()
{
base.Update();
API.Update();
}
protected override void Dispose(bool isDisposing)
{
//refresh token may have changed.
if (LocalConfig != null && API != null)
{
LocalConfig.Set(OsuSetting.Token, LocalConfig.Get<bool>(OsuSetting.SavePassword) ? API.Token : string.Empty);
LocalConfig.Save();
}
base.Dispose(isDisposing);
}
private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>(); private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>();
public void Import(params string[] paths) public void Import(params string[] paths)

View File

@ -186,7 +186,7 @@ namespace osu.Game.Overlays.Direct
progressBar.FadeOut(500); progressBar.FadeOut(500);
}; };
request.DownloadProgressed += progress => progressBar.Current.Value = progress; request.DownloadProgressed += progress => Schedule(() => progressBar.Current.Value = progress);
request.Success += data => request.Success += data =>
{ {

View File

@ -210,7 +210,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
PlaceholderText = "Email address", PlaceholderText = "Email address",
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Text = api?.Username ?? string.Empty, Text = api?.ProvidedUsername ?? string.Empty,
TabbableContentContainer = this TabbableContentContainer = this
}, },
password = new OsuPasswordTextBox password = new OsuPasswordTextBox