adding signalr project
This commit is contained in:
parent
b9cc6d5d45
commit
562c119e18
@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.Event", "Selector.
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.Data", "Selector.Data\Selector.Data.csproj", "{CB62ACCB-94F1-4B78-A195-8B108B9E800D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.SignalR", "Selector.SignalR\Selector.SignalR.csproj", "{089C9DE8-2B73-4341-BA17-572CD6BAD14D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -57,6 +59,10 @@ Global
|
||||
{CB62ACCB-94F1-4B78-A195-8B108B9E800D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CB62ACCB-94F1-4B78-A195-8B108B9E800D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CB62ACCB-94F1-4B78-A195-8B108B9E800D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{089C9DE8-2B73-4341-BA17-572CD6BAD14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{089C9DE8-2B73-4341-BA17-572CD6BAD14D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{089C9DE8-2B73-4341-BA17-572CD6BAD14D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{089C9DE8-2B73-4341-BA17-572CD6BAD14D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
40
Selector.SignalR/BaseSignalRClient.cs
Normal file
40
Selector.SignalR/BaseSignalRClient.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public abstract class BaseSignalRClient: IAsyncDisposable
|
||||
{
|
||||
private readonly string _baseUrl;
|
||||
protected HubConnection hubConnection;
|
||||
|
||||
public BaseSignalRClient(string path)
|
||||
{
|
||||
var baseOverride = Environment.GetEnvironmentVariable("SELECTOR_BASE_URL");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(baseOverride))
|
||||
{
|
||||
_baseUrl = baseOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
_baseUrl = "https://selector.sarsoo.xyz";
|
||||
}
|
||||
|
||||
hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(_baseUrl + "/" + path)
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return ((IAsyncDisposable)hubConnection).DisposeAsync();
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
await hubConnection.StartAsync();
|
||||
}
|
||||
}
|
||||
|
24
Selector.SignalR/INow.cs
Normal file
24
Selector.SignalR/INow.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using SpotifyAPI.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface INowPlayingHubClient
|
||||
{
|
||||
public Task OnNewPlaying(CurrentlyPlayingDTO context);
|
||||
public Task OnNewAudioFeature(TrackAudioFeatures features);
|
||||
public Task OnNewPlayCount(PlayCount playCount);
|
||||
public Task OnNewCard(ICard card);
|
||||
}
|
||||
|
||||
public interface INowPlayingHub
|
||||
{
|
||||
Task OnConnected();
|
||||
Task PlayDensityFacts(string track, string artist, string album, string albumArtist);
|
||||
Task SendAudioFeatures(string trackId);
|
||||
Task SendFacts(string track, string artist, string album, string albumArtist);
|
||||
Task SendNewPlaying();
|
||||
Task SendPlayCount(string track, string artist, string album, string albumArtist);
|
||||
}
|
||||
|
14
Selector.SignalR/IPast.cs
Normal file
14
Selector.SignalR/IPast.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface IPastHub
|
||||
{
|
||||
Task OnConnected();
|
||||
Task OnSubmitted(IPastParams param);
|
||||
}
|
||||
|
||||
public interface IPastHubClient
|
||||
{
|
||||
public Task OnRankResult(IRankResult result);
|
||||
}
|
6
Selector.SignalR/Models/ICard.cs
Normal file
6
Selector.SignalR/Models/ICard.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface ICard
|
||||
{
|
||||
string Content { get; set; }
|
||||
}
|
7
Selector.SignalR/Models/IChartEntry.cs
Normal file
7
Selector.SignalR/Models/IChartEntry.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface IChartEntry
|
||||
{
|
||||
string Name { get; set; }
|
||||
int Value { get; set; }
|
||||
}
|
10
Selector.SignalR/Models/IPastParams.cs
Normal file
10
Selector.SignalR/Models/IPastParams.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface IPastParams
|
||||
{
|
||||
string Track { get; set; }
|
||||
string Album { get; set; }
|
||||
string Artist { get; set; }
|
||||
string From { get; set; }
|
||||
string To { get; set; }
|
||||
}
|
12
Selector.SignalR/Models/IRankResult.cs
Normal file
12
Selector.SignalR/Models/IRankResult.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public interface IRankResult
|
||||
{
|
||||
IEnumerable<IChartEntry> TrackEntries { get; set; }
|
||||
IEnumerable<IChartEntry> AlbumEntries { get; set; }
|
||||
IEnumerable<IChartEntry> ArtistEntries { get; set; }
|
||||
IEnumerable<CountSample> ResampledSeries { get; set; }
|
||||
int TotalCount { get; set; }
|
||||
}
|
98
Selector.SignalR/NowHubClient.cs
Normal file
98
Selector.SignalR/NowHubClient.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using SpotifyAPI.Web;
|
||||
|
||||
namespace Selector.SignalR;
|
||||
|
||||
public class NowHubClient: BaseSignalRClient, INowPlayingHub, IDisposable
|
||||
{
|
||||
private List<IDisposable> NewPlayingCallbacks = new();
|
||||
private List<IDisposable> NewAudioFeatureCallbacks = new();
|
||||
private List<IDisposable> NewPlayCountCallbacks = new();
|
||||
private List<IDisposable> NewCardCallbacks = new();
|
||||
private bool disposedValue;
|
||||
|
||||
public NowHubClient(): base("nowhub")
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNewPlaying(Action<CurrentlyPlayingDTO> action)
|
||||
{
|
||||
NewPlayingCallbacks.Add(hubConnection.On(nameof(OnNewPlaying), action));
|
||||
}
|
||||
|
||||
public void OnNewAudioFeature(Action<TrackAudioFeatures> action)
|
||||
{
|
||||
NewAudioFeatureCallbacks.Add(hubConnection.On(nameof(OnNewAudioFeature), action));
|
||||
}
|
||||
|
||||
public void OnNewPlayCount(Action<PlayCount> action)
|
||||
{
|
||||
NewPlayCountCallbacks.Add(hubConnection.On(nameof(OnNewPlayCount), action));
|
||||
}
|
||||
|
||||
public void OnNewCard(Action<ICard> action)
|
||||
{
|
||||
NewCardCallbacks.Add(hubConnection.On(nameof(OnNewCard), action));
|
||||
}
|
||||
|
||||
public Task OnConnected()
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(OnConnected));
|
||||
}
|
||||
|
||||
public Task PlayDensityFacts(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(PlayDensityFacts), track, artist, album, albumArtist);
|
||||
}
|
||||
|
||||
public Task SendAudioFeatures(string trackId)
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(SendAudioFeatures), trackId);
|
||||
}
|
||||
|
||||
public Task SendFacts(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(SendFacts), track, artist, album, albumArtist);
|
||||
}
|
||||
|
||||
public Task SendNewPlaying()
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(SendNewPlaying));
|
||||
}
|
||||
|
||||
public Task SendPlayCount(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
return hubConnection.InvokeAsync(nameof(SendPlayCount), track, artist, album, albumArtist);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach(var callback in NewPlayingCallbacks
|
||||
.Concat(NewAudioFeatureCallbacks)
|
||||
.Concat(NewPlayCountCallbacks)
|
||||
.Concat(NewCardCallbacks))
|
||||
{
|
||||
callback.Dispose();
|
||||
}
|
||||
|
||||
base.DisposeAsync();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
25
Selector.SignalR/Selector.SignalR.csproj
Normal file
25
Selector.SignalR/Selector.SignalR.csproj
Normal file
@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Selector\Selector.csproj" />
|
||||
<!-- <ProjectReference Include="..\Selector.Model\Selector.Model.csproj" /> -->
|
||||
</ItemGroup>
|
||||
<!-- <ItemGroup>
|
||||
<None Remove="Microsoft.AspNetCore.SignalR.Client" />
|
||||
</ItemGroup> -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Models\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Selector.Web.Service;
|
||||
using Selector.Web.Hubs;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web.Extensions
|
||||
{
|
||||
|
@ -11,21 +11,14 @@ using Microsoft.Extensions.Options;
|
||||
using Selector.Cache;
|
||||
using Selector.Model;
|
||||
using Selector.Model.Extensions;
|
||||
using Selector.SignalR;
|
||||
using Selector.Web.NowPlaying;
|
||||
using SpotifyAPI.Web;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Selector.Web.Hubs
|
||||
{
|
||||
public interface INowPlayingHubClient
|
||||
{
|
||||
public Task OnNewPlaying(CurrentlyPlayingDTO context);
|
||||
public Task OnNewAudioFeature(TrackAudioFeatures features);
|
||||
public Task OnNewPlayCount(PlayCount playCount);
|
||||
public Task OnNewCard(Card card);
|
||||
}
|
||||
|
||||
public class NowPlayingHub: Hub<INowPlayingHubClient>
|
||||
public class NowPlayingHub : Hub<INowPlayingHubClient>, INowPlayingHub
|
||||
{
|
||||
private readonly IDatabaseAsync Cache;
|
||||
private readonly AudioFeaturePuller AudioFeaturePuller;
|
||||
@ -37,8 +30,8 @@ namespace Selector.Web.Hubs
|
||||
private readonly IOptions<NowPlayingOptions> nowOptions;
|
||||
|
||||
public NowPlayingHub(
|
||||
IDatabaseAsync cache,
|
||||
AudioFeaturePuller featurePuller,
|
||||
IDatabaseAsync cache,
|
||||
AudioFeaturePuller featurePuller,
|
||||
ApplicationDbContext db,
|
||||
IScrobbleRepository scrobbleRepository,
|
||||
IOptions<NowPlayingOptions> options,
|
||||
@ -77,15 +70,15 @@ namespace Selector.Web.Hubs
|
||||
var user = Db.Users
|
||||
.AsNoTracking()
|
||||
.Where(u => u.Id == Context.UserIdentifier)
|
||||
.SingleOrDefault()
|
||||
.SingleOrDefault()
|
||||
?? throw new SqlNullValueException("No user returned");
|
||||
var watcher = Db.Watcher
|
||||
.AsNoTracking()
|
||||
.Where(w => w.UserId == Context.UserIdentifier
|
||||
&& w.Type == WatcherType.Player)
|
||||
.SingleOrDefault()
|
||||
.SingleOrDefault()
|
||||
?? throw new SqlNullValueException($"No player watcher found for [{user.UserName}]");
|
||||
|
||||
|
||||
var feature = await AudioFeaturePuller.Get(user.SpotifyRefreshToken, trackId);
|
||||
|
||||
if (feature is not null)
|
||||
@ -96,7 +89,7 @@ namespace Selector.Web.Hubs
|
||||
|
||||
public async Task SendPlayCount(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
if(PlayCountPuller is not null)
|
||||
if (PlayCountPuller is not null)
|
||||
{
|
||||
var user = Db.Users
|
||||
.AsNoTracking()
|
||||
@ -124,17 +117,13 @@ namespace Selector.Web.Hubs
|
||||
|
||||
public async Task SendFacts(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
var user = Db.Users
|
||||
.AsNoTracking()
|
||||
.Where(u => u.Id == Context.UserIdentifier)
|
||||
.SingleOrDefault()
|
||||
?? throw new SqlNullValueException("No user returned");
|
||||
|
||||
await PlayDensityFacts(user, track, artist, album, albumArtist);
|
||||
await PlayDensityFacts(track, artist, album, albumArtist);
|
||||
}
|
||||
|
||||
public async Task PlayDensityFacts(ApplicationUser user, string track, string artist, string album, string albumArtist)
|
||||
public async Task PlayDensityFacts(string track, string artist, string album, string albumArtist)
|
||||
{
|
||||
var user = await Db.Users.AsNoTracking().FirstOrDefaultAsync(u => u.Id == Context.UserIdentifier);
|
||||
|
||||
if (user.ScrobbleSavingEnabled())
|
||||
{
|
||||
var artistScrobbles = ScrobbleRepository.GetAll(userId: user.Id, artistName: artist, from: GetMaximumWindow()).ToArray();
|
||||
@ -144,7 +133,7 @@ namespace Selector.Web.Hubs
|
||||
|
||||
if (artistDensity > nowOptions.Value.ArtistDensityThreshold)
|
||||
{
|
||||
tasks.Add(Clients.Caller.OnNewCard(new()
|
||||
tasks.Add(Clients.Caller.OnNewCard(new Card()
|
||||
{
|
||||
Content = $"You're on a {artist} binge! {artistDensity} plays/day recently"
|
||||
}));
|
||||
@ -154,7 +143,7 @@ namespace Selector.Web.Hubs
|
||||
|
||||
if (albumDensity > nowOptions.Value.AlbumDensityThreshold)
|
||||
{
|
||||
tasks.Add(Clients.Caller.OnNewCard(new()
|
||||
tasks.Add(Clients.Caller.OnNewCard(new Card()
|
||||
{
|
||||
Content = $"You're on a {album} binge! {albumDensity} plays/day recently"
|
||||
}));
|
||||
@ -164,13 +153,13 @@ namespace Selector.Web.Hubs
|
||||
|
||||
if (albumDensity > nowOptions.Value.TrackDensityThreshold)
|
||||
{
|
||||
tasks.Add(Clients.Caller.OnNewCard(new()
|
||||
tasks.Add(Clients.Caller.OnNewCard(new Card()
|
||||
{
|
||||
Content = $"You're on a {track} binge! {trackDensity} plays/day recently"
|
||||
}));
|
||||
}
|
||||
|
||||
if(tasks.Any())
|
||||
if (tasks.Any())
|
||||
{
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
@ -7,16 +7,12 @@ using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Selector.Cache;
|
||||
using Selector.Model;
|
||||
using Selector.SignalR;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace Selector.Web.Hubs
|
||||
{
|
||||
public interface IPastHubClient
|
||||
{
|
||||
public Task OnRankResult(RankResult result);
|
||||
}
|
||||
|
||||
public class PastHub: Hub<IPastHubClient>
|
||||
public class PastHub : Hub<IPastHubClient>, IPastHub
|
||||
{
|
||||
private readonly IDatabaseAsync Cache;
|
||||
private readonly AudioFeaturePuller AudioFeaturePuller;
|
||||
@ -28,8 +24,8 @@ namespace Selector.Web.Hubs
|
||||
private readonly IOptions<PastOptions> pastOptions;
|
||||
|
||||
public PastHub(
|
||||
IDatabaseAsync cache,
|
||||
AudioFeaturePuller featurePuller,
|
||||
IDatabaseAsync cache,
|
||||
AudioFeaturePuller featurePuller,
|
||||
ApplicationDbContext db,
|
||||
IListenRepository listenRepository,
|
||||
IOptions<PastOptions> options,
|
||||
@ -61,7 +57,7 @@ namespace Selector.Web.Hubs
|
||||
" (Expanded Edition)",
|
||||
};
|
||||
|
||||
public async Task OnSubmitted(PastParams param)
|
||||
public async Task OnSubmitted(IPastParams param)
|
||||
{
|
||||
param.Track = string.IsNullOrWhiteSpace(param.Track) ? null : param.Track;
|
||||
param.Album = string.IsNullOrWhiteSpace(param.Album) ? null : param.Album;
|
||||
@ -111,7 +107,7 @@ namespace Selector.Web.Hubs
|
||||
.Take(pastOptions.Value.RankingCount)
|
||||
.ToArray();
|
||||
|
||||
await Clients.Caller.OnRankResult(new()
|
||||
await Clients.Caller.OnRankResult(new RankResult()
|
||||
{
|
||||
TrackEntries = trackGrouped.Select(x => new ChartEntry()
|
||||
{
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
namespace Selector.Web.NowPlaying
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web.NowPlaying;
|
||||
|
||||
public class Card : ICard
|
||||
{
|
||||
public class Card
|
||||
{
|
||||
public string Content { get; set; }
|
||||
}
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web;
|
||||
|
||||
public class ChartEntry
|
||||
public class ChartEntry : IChartEntry
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Value { get; set; }
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web;
|
||||
|
||||
public class PastParams
|
||||
public class PastParams : IPastParams
|
||||
{
|
||||
public string Track { get; set; }
|
||||
public string Album { get; set; }
|
||||
|
@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web;
|
||||
|
||||
public class RankResult
|
||||
public class RankResult : IRankResult
|
||||
{
|
||||
public IEnumerable<ChartEntry> TrackEntries { get; set; }
|
||||
public IEnumerable<ChartEntry> AlbumEntries { get; set; }
|
||||
public IEnumerable<ChartEntry> ArtistEntries { get; set; }
|
||||
public IEnumerable<IChartEntry> TrackEntries { get; set; }
|
||||
public IEnumerable<IChartEntry> AlbumEntries { get; set; }
|
||||
public IEnumerable<IChartEntry> ArtistEntries { get; set; }
|
||||
|
||||
public IEnumerable<CountSample> ResampledSeries { get; set; }
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
<ProjectReference Include="..\Selector.Model\Selector.Model.csproj" />
|
||||
<ProjectReference Include="..\Selector.Cache\Selector.Cache.csproj" />
|
||||
<ProjectReference Include="..\Selector.Event\Selector.Event.csproj" />
|
||||
<ProjectReference Include="..\Selector.SignalR\Selector.SignalR.csproj">
|
||||
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
using Selector.Web.Hubs;
|
||||
using Selector.Events;
|
||||
using Selector.SignalR;
|
||||
|
||||
namespace Selector.Web.Service
|
||||
{
|
||||
|
@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.Data", "Selector.D
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.MAUI", "Selector.MAUI\Selector.MAUI.csproj", "{090ADE89-4119-43D7-B108-3357B7D676FC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Selector.SignalR", "Selector.SignalR\Selector.SignalR.csproj", "{F41D98F2-7684-4786-969C-BFC8DF7FB489}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -63,6 +65,10 @@ Global
|
||||
{090ADE89-4119-43D7-B108-3357B7D676FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{090ADE89-4119-43D7-B108-3357B7D676FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{090ADE89-4119-43D7-B108-3357B7D676FC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F41D98F2-7684-4786-969C-BFC8DF7FB489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F41D98F2-7684-4786-969C-BFC8DF7FB489}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F41D98F2-7684-4786-969C-BFC8DF7FB489}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F41D98F2-7684-4786-969C-BFC8DF7FB489}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
Loading…
Reference in New Issue
Block a user