use refit for client
This commit is contained in:
@@ -1,14 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TorchRemote.Models.Requests;
|
using Refit;
|
||||||
using TorchRemote.Models.Responses;
|
|
||||||
using TorchRemote.Models.Shared;
|
|
||||||
using Websocket.Client;
|
using Websocket.Client;
|
||||||
namespace TorchRemote.Services;
|
namespace TorchRemote.Services;
|
||||||
|
|
||||||
@@ -31,8 +26,10 @@ public class ApiClientService
|
|||||||
|
|
||||||
public ApiClientService()
|
public ApiClientService()
|
||||||
{
|
{
|
||||||
|
Api = RestService.For<IRemoteApi>(_client);
|
||||||
Task.Run(ConnectionTimer);
|
Task.Run(ConnectionTimer);
|
||||||
}
|
}
|
||||||
|
public IRemoteApi Api { get; }
|
||||||
|
|
||||||
private async Task ConnectionTimer()
|
private async Task ConnectionTimer()
|
||||||
{
|
{
|
||||||
@@ -41,7 +38,7 @@ public class ApiClientService
|
|||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await GetServerStatusAsync(CancellationToken.None);
|
await Api.GetServerStatus();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -52,43 +49,6 @@ public class ApiClientService
|
|||||||
Connected?.Invoke(this, EventArgs.Empty);
|
Connected?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ServerStatusResponse> GetServerStatusAsync(CancellationToken token) =>
|
|
||||||
_client.GetFromJsonAsync<ServerStatusResponse>("server/status", token)!;
|
|
||||||
|
|
||||||
public Task<ServerSettings> GetServerSettingsAsync(CancellationToken token) =>
|
|
||||||
_client.GetFromJsonAsync<ServerSettings>("server/settings", token)!;
|
|
||||||
|
|
||||||
public Task SetServerSettingsAsync(ServerSettings settings, CancellationToken token) =>
|
|
||||||
_client.PostAsJsonAsync("server/settings", settings, token);
|
|
||||||
|
|
||||||
public Task StartServerAsync(CancellationToken token) =>
|
|
||||||
_client.PostAsync("server/start", null, token);
|
|
||||||
|
|
||||||
public Task StopServerAsync(StopServerRequest request, CancellationToken token) =>
|
|
||||||
_client.PostAsJsonAsync("server/stop", request, token);
|
|
||||||
|
|
||||||
public Task<IEnumerable<Guid>> GetWorldsAsync(CancellationToken token) =>
|
|
||||||
_client.GetFromJsonAsync<IEnumerable<Guid>>("worlds", token)!;
|
|
||||||
|
|
||||||
public Task<WorldResponse> GetWorldAsync(Guid id, CancellationToken token) =>
|
|
||||||
_client.GetFromJsonAsync<WorldResponse>($"worlds/{id}", token)!;
|
|
||||||
|
|
||||||
public Task<Guid> GetSelectedWorld(CancellationToken token) =>
|
|
||||||
_client.GetFromJsonAsync<Guid>("worlds/selected", token);
|
|
||||||
|
|
||||||
public Task SelectWorldAsync(Guid id, CancellationToken token) =>
|
|
||||||
_client.PostAsync($"worlds/{id}/select", null, token);
|
|
||||||
|
|
||||||
public Task SendChatMessageAsync(ChatMessageRequest request, CancellationToken token) =>
|
|
||||||
_client.PostAsJsonAsync("chat/message", request, token);
|
|
||||||
|
|
||||||
public async Task<Guid> InvokeCommandAsync(ChatCommandRequest request, CancellationToken token)
|
|
||||||
{
|
|
||||||
var r = await _client.PostAsJsonAsync("chat/command", request, token);
|
|
||||||
r.EnsureSuccessStatusCode();
|
|
||||||
return await r.Content.ReadFromJsonAsync<Guid>(cancellationToken: token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<WebsocketClient> WatchChatAsync() => StartWebsocketConnectionAsync("live/chat");
|
public Task<WebsocketClient> WatchChatAsync() => StartWebsocketConnectionAsync("live/chat");
|
||||||
|
|
||||||
public Task<WebsocketClient> WatchLogLinesAsync() => StartWebsocketConnectionAsync("live/logs");
|
public Task<WebsocketClient> WatchLogLinesAsync() => StartWebsocketConnectionAsync("live/logs");
|
||||||
|
47
TorchRemote/Services/IRemoteApi.cs
Normal file
47
TorchRemote/Services/IRemoteApi.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Refit;
|
||||||
|
using TorchRemote.Models.Requests;
|
||||||
|
using TorchRemote.Models.Responses;
|
||||||
|
using TorchRemote.Models.Shared;
|
||||||
|
namespace TorchRemote.Services;
|
||||||
|
|
||||||
|
public interface IRemoteApi
|
||||||
|
{
|
||||||
|
#region Server
|
||||||
|
[Get("/server/status")]
|
||||||
|
Task<ServerStatusResponse> GetServerStatus();
|
||||||
|
[Post("/server/start")]
|
||||||
|
Task StartServer();
|
||||||
|
[Post("/server/stop")]
|
||||||
|
Task StopServer([Body] StopServerRequest request);
|
||||||
|
[Get("/server/settings")]
|
||||||
|
Task<ServerSettings> GetServerSettings();
|
||||||
|
[Post("/server/settings")]
|
||||||
|
Task SetServerSettings([Body] ServerSettings request);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Chat
|
||||||
|
[Post("/chat/message")]
|
||||||
|
Task SendChatMessage([Body] ChatMessageRequest request);
|
||||||
|
[Post("/chat/command")]
|
||||||
|
Task<Guid> InvokeChatCommand([Body] ChatCommandRequest request);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Worlds
|
||||||
|
[Get("/worlds")]
|
||||||
|
Task<IEnumerable<Guid>> GetWorlds();
|
||||||
|
[Get("/worlds/selected")]
|
||||||
|
Task<Guid> GetSelectedWorld();
|
||||||
|
[Get("/worlds/{id}")]
|
||||||
|
Task<WorldResponse> GetWorld(Guid id);
|
||||||
|
[Post("/worlds/{id}/select")]
|
||||||
|
Task SelectWorld(Guid id);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Settings
|
||||||
|
[Get("/settings/{id}")]
|
||||||
|
Task<SettingInfoResponse> GetSetting(Guid id);
|
||||||
|
#endregion
|
||||||
|
}
|
@@ -25,6 +25,7 @@
|
|||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.16" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.16" />
|
||||||
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
|
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="18.3.1" />
|
<PackageReference Include="ReactiveUI.Fody" Version="18.3.1" />
|
||||||
|
<PackageReference Include="Refit" Version="6.3.2" />
|
||||||
<PackageReference Include="System.Text.Json" Version="7.0.0-preview.6.22324.4" />
|
<PackageReference Include="System.Text.Json" Version="7.0.0-preview.6.22324.4" />
|
||||||
<PackageReference Include="Websocket.Client" Version="4.4.43" />
|
<PackageReference Include="Websocket.Client" Version="4.4.43" />
|
||||||
<PackageReference Include="XamlNameReferenceGenerator" Version="1.3.4" />
|
<PackageReference Include="XamlNameReferenceGenerator" Version="1.3.4" />
|
||||||
|
@@ -34,9 +34,9 @@ public class ChatViewModel : ViewModelBase
|
|||||||
.Subscribe(s => ChatLines += $"{s}{Environment.NewLine}");
|
.Subscribe(s => ChatLines += $"{s}{Environment.NewLine}");
|
||||||
});
|
});
|
||||||
|
|
||||||
SendMessageCommand = ReactiveCommand.CreateFromTask<string>((s, t) => s.StartsWith("!") ?
|
SendMessageCommand = ReactiveCommand.CreateFromTask<string>(s => s.StartsWith("!") ?
|
||||||
clientService.InvokeCommandAsync(new(s[(s.IndexOf('!') + 1)..]), t) :
|
clientService.Api.InvokeChatCommand(new(s[(s.IndexOf('!') + 1)..])) :
|
||||||
clientService.SendChatMessageAsync(new("Server", s, ChatChannel.GlobalScripted), t));
|
clientService.Api.SendChatMessage(new("Server", s, ChatChannel.GlobalScripted)));
|
||||||
|
|
||||||
InvalidCommandPopup = SendMessageCommand.ThrownExceptions
|
InvalidCommandPopup = SendMessageCommand.ThrownExceptions
|
||||||
.Where(b => b is HttpRequestException {StatusCode: HttpStatusCode.NotFound or HttpStatusCode.BadRequest})
|
.Where(b => b is HttpRequestException {StatusCode: HttpStatusCode.NotFound or HttpStatusCode.BadRequest})
|
||||||
|
@@ -22,7 +22,7 @@ public class DashboardViewModel : ViewModelBase
|
|||||||
.Subscribe(_ =>
|
.Subscribe(_ =>
|
||||||
{
|
{
|
||||||
Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(10))
|
Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(10))
|
||||||
.Select(_ => Observable.FromAsync(t => _clientService.GetServerStatusAsync(t)))
|
.Select(_ => Observable.FromAsync(() => _clientService.Api.GetServerStatus()))
|
||||||
.Concat()
|
.Concat()
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
.Subscribe(r =>
|
.Subscribe(r =>
|
||||||
@@ -49,11 +49,11 @@ public class DashboardViewModel : ViewModelBase
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
StartCommand = ReactiveCommand.CreateFromTask(t => _clientService.StartServerAsync(t),
|
StartCommand = ReactiveCommand.CreateFromTask(() => _clientService.Api.StartServer(),
|
||||||
this.WhenAnyValue(x => x.Status)
|
this.WhenAnyValue(x => x.Status)
|
||||||
.Select(b => b is ServerStatus.Stopped));
|
.Select(b => b is ServerStatus.Stopped));
|
||||||
|
|
||||||
StopCommand = ReactiveCommand.CreateFromTask<bool>((b, t) => _clientService.StopServerAsync(new(b), t),
|
StopCommand = ReactiveCommand.CreateFromTask<bool>(b => _clientService.Api.StopServer(new(b)),
|
||||||
this.WhenAnyValue(x => x.Status)
|
this.WhenAnyValue(x => x.Status)
|
||||||
.Select(b => b is ServerStatus.Running));
|
.Select(b => b is ServerStatus.Running));
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ public class ServerConfigViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
.Select(_ => Observable.FromAsync(clientService.GetServerSettingsAsync))
|
.Select(_ => Observable.FromAsync(clientService.Api.GetServerSettings))
|
||||||
.Concat()
|
.Concat()
|
||||||
.Subscribe(b =>
|
.Subscribe(b =>
|
||||||
{
|
{
|
||||||
@@ -24,33 +24,33 @@ public class ServerConfigViewModel : ViewModelBase
|
|||||||
Port = b.ListenEndPoint.Port;
|
Port = b.ListenEndPoint.Port;
|
||||||
});
|
});
|
||||||
|
|
||||||
SaveCommand = ReactiveCommand.CreateFromTask(t =>
|
SaveCommand = ReactiveCommand.CreateFromTask(() =>
|
||||||
clientService.SetServerSettingsAsync(new(
|
clientService.Api.SetServerSettings(new(
|
||||||
Name,
|
Name,
|
||||||
MapName,
|
MapName,
|
||||||
Description,
|
Description,
|
||||||
MemberLimit,
|
MemberLimit,
|
||||||
new(Ip, Port)
|
new(Ip, Port)
|
||||||
), t));
|
)));
|
||||||
|
|
||||||
Worlds = Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
Worlds = Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
.Select(_ => Observable.FromAsync(clientService.GetWorldsAsync))
|
.Select(_ => Observable.FromAsync(clientService.Api.GetWorlds))
|
||||||
.Concat()
|
.Concat()
|
||||||
.SelectMany(ids => ids)
|
.SelectMany(ids => ids)
|
||||||
.Select(id => Observable.FromAsync(t => clientService.GetWorldAsync(id, t)).Select(b => new World(id, b.Name, b.SizeKb)))
|
.Select(id => Observable.FromAsync(() => clientService.Api.GetWorld(id)).Select(b => new World(id, b.Name, b.SizeKb)))
|
||||||
.Concat();
|
.Concat();
|
||||||
|
|
||||||
Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
Observable.FromEventPattern(clientService, nameof(clientService.Connected))
|
||||||
.ObserveOn(RxApp.MainThreadScheduler)
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
.Select(_ => Observable.FromAsync(clientService.GetSelectedWorld))
|
.Select(_ => Observable.FromAsync(clientService.Api.GetSelectedWorld))
|
||||||
.Concat()
|
.Concat()
|
||||||
.Select(id => Observable.FromAsync(t => clientService.GetWorldAsync(id, t)).Select(b => new World(id, b.Name, b.SizeKb)))
|
.Select(id => Observable.FromAsync(() => clientService.Api.GetWorld(id)).Select(b => new World(id, b.Name, b.SizeKb)))
|
||||||
.Concat()
|
.Concat()
|
||||||
.BindTo(this, x => x.SelectedWorld);
|
.BindTo(this, x => x.SelectedWorld);
|
||||||
|
|
||||||
this.ObservableForProperty(x => x.SelectedWorld)
|
this.ObservableForProperty(x => x.SelectedWorld)
|
||||||
.Select(world => Observable.FromAsync(t => clientService.SelectWorldAsync(world.Value!.Id, t)))
|
.Select(world => Observable.FromAsync(() => clientService.Api.SelectWorld(world.Value!.Id)))
|
||||||
.Concat()
|
.Concat()
|
||||||
.Subscribe(_ => { });
|
.Subscribe(_ => { });
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user