mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-23 14:46:26 +00:00
Finished UWP Example using protocol registration - Docs TODO
This commit is contained in:
parent
d095a5a870
commit
24bb3d345f
@ -80,30 +80,6 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri BuildLoginUri(LoginRequest request)
|
|
||||||
{
|
|
||||||
Ensure.ArgumentNotNull(request, nameof(request));
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder(SpotifyUrls.Authorize.ToString());
|
|
||||||
builder.Append($"?client_id={request.ClientId}");
|
|
||||||
builder.Append($"&response_type={request.ResponseTypeParam.ToString().ToLower()}");
|
|
||||||
builder.Append($"&redirect_uri={HttpUtility.UrlEncode(BaseUri.ToString())}");
|
|
||||||
if (!string.IsNullOrEmpty(request.State))
|
|
||||||
{
|
|
||||||
builder.Append($"&state={HttpUtility.UrlEncode(request.State)}");
|
|
||||||
}
|
|
||||||
if (request.Scope != null)
|
|
||||||
{
|
|
||||||
builder.Append($"&scope={HttpUtility.UrlEncode(string.Join(" ", request.Scope))}");
|
|
||||||
}
|
|
||||||
if (request.ShowDialog != null)
|
|
||||||
{
|
|
||||||
builder.Append($"&show_dialog={request.ShowDialog.Value}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Uri(builder.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
@ -12,8 +12,6 @@ namespace SpotifyAPI.Web.Auth
|
|||||||
Task Start();
|
Task Start();
|
||||||
Task Stop();
|
Task Stop();
|
||||||
|
|
||||||
Uri BuildLoginUri(LoginRequest request);
|
|
||||||
|
|
||||||
Uri BaseUri { get; }
|
Uri BaseUri { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
namespace SpotifyAPI.Web.Auth
|
|
||||||
{
|
|
||||||
public class LoginRequest
|
|
||||||
{
|
|
||||||
public LoginRequest(string clientId, ResponseType responseType)
|
|
||||||
{
|
|
||||||
Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId));
|
|
||||||
|
|
||||||
ClientId = clientId;
|
|
||||||
ResponseTypeParam = responseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResponseType ResponseTypeParam { get; }
|
|
||||||
public string ClientId { get; }
|
|
||||||
public string State { get; set; }
|
|
||||||
public ICollection<string> Scope { get; set; }
|
|
||||||
public bool? ShowDialog { get; set; }
|
|
||||||
|
|
||||||
public enum ResponseType
|
|
||||||
{
|
|
||||||
Code,
|
|
||||||
Token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,19 +26,19 @@ namespace Example.CLI.CustomHTML
|
|||||||
|
|
||||||
_server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;
|
_server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;
|
||||||
|
|
||||||
var request = new LoginRequest(clientId, LoginRequest.ResponseType.Code)
|
var request = new LoginRequest(_server.BaseUri, clientId, LoginRequest.ResponseType.Code)
|
||||||
{
|
{
|
||||||
Scope = new List<string> { UserReadEmail }
|
Scope = new List<string> { UserReadEmail }
|
||||||
};
|
};
|
||||||
|
|
||||||
Uri url = _server.BuildLoginUri(request);
|
Uri uri = request.ToUri();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BrowserUtil.Open(url);
|
BrowserUtil.Open(uri);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Unable to open URL, manually open: {0}", url);
|
Console.WriteLine("Unable to open URL, manually open: {0}", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
|
@ -65,19 +65,19 @@ namespace Example.CLI.PersistentConfig
|
|||||||
await _server.Start();
|
await _server.Start();
|
||||||
_server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;
|
_server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;
|
||||||
|
|
||||||
var request = new LoginRequest(clientId, LoginRequest.ResponseType.Code)
|
var request = new LoginRequest(_server.BaseUri, clientId, LoginRequest.ResponseType.Code)
|
||||||
{
|
{
|
||||||
Scope = new List<string> { UserReadEmail, UserReadPrivate, PlaylistReadPrivate }
|
Scope = new List<string> { UserReadEmail, UserReadPrivate, PlaylistReadPrivate }
|
||||||
};
|
};
|
||||||
|
|
||||||
Uri url = _server.BuildLoginUri(request);
|
Uri uri = request.ToUri();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BrowserUtil.Open(url);
|
BrowserUtil.Open(uri);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Unable to open URL, manually open: {0}", url);
|
Console.WriteLine("Unable to open URL, manually open: {0}", uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<Application
|
<local:ExampleApp x:Class="Example.UWP.App"
|
||||||
x:Class="UWP.App"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:local="using:Example.UWP"
|
||||||
xmlns:local="using:UWP">
|
RequestedTheme="Dark">
|
||||||
|
<Application.Resources>
|
||||||
</Application>
|
<x:String x:Key="WelcomeText">Hello World!</x:String>
|
||||||
|
</Application.Resources>
|
||||||
|
</local:ExampleApp>
|
||||||
|
@ -1,100 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using MvvmCross;
|
||||||
using System.IO;
|
using MvvmCross.Platforms.Uap.Core;
|
||||||
using System.Linq;
|
using MvvmCross.Platforms.Uap.Views;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
using Windows.Foundation;
|
using Windows.UI.Popups;
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace Example.UWP
|
namespace Example.UWP
|
||||||
{
|
{
|
||||||
|
public abstract class ExampleApp : MvxApplication<MvxWindowsSetup<CoreApp>, CoreApp>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class App
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides application-specific behavior to supplement the default Application class.
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
sealed partial class App : Application
|
public App()
|
||||||
{
|
{
|
||||||
/// <summary>
|
InitializeComponent();
|
||||||
/// Initializes the singleton application object. This is the first line of authored code
|
|
||||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
|
||||||
/// </summary>
|
|
||||||
public App()
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
this.Suspending += OnSuspending;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
|
||||||
/// will be used such as when the application is launched to open a specific file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="e">Details about the launch request and process.</param>
|
|
||||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
|
||||||
{
|
|
||||||
Frame rootFrame = Window.Current.Content as Frame;
|
|
||||||
|
|
||||||
// Do not repeat app initialization when the Window already has content,
|
|
||||||
// just ensure that the window is active
|
|
||||||
if (rootFrame == null)
|
|
||||||
{
|
|
||||||
// Create a Frame to act as the navigation context and navigate to the first page
|
|
||||||
rootFrame = new Frame();
|
|
||||||
|
|
||||||
rootFrame.NavigationFailed += OnNavigationFailed;
|
|
||||||
|
|
||||||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
|
||||||
{
|
|
||||||
//TODO: Load state from previously suspended application
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place the frame in the current Window
|
|
||||||
Window.Current.Content = rootFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.PrelaunchActivated == false)
|
|
||||||
{
|
|
||||||
if (rootFrame.Content == null)
|
|
||||||
{
|
|
||||||
// When the navigation stack isn't restored navigate to the first page,
|
|
||||||
// configuring the new page by passing required information as a navigation
|
|
||||||
// parameter
|
|
||||||
rootFrame.Navigate(typeof(MainPage), e.Arguments);
|
|
||||||
}
|
|
||||||
// Ensure the current window is active
|
|
||||||
Window.Current.Activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when Navigation to a certain page fails
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The Frame which failed navigation</param>
|
|
||||||
/// <param name="e">Details about the navigation failure</param>
|
|
||||||
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when application execution is being suspended. Application state is saved
|
|
||||||
/// without knowing whether the application will be terminated or resumed with the contents
|
|
||||||
/// of memory still intact.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The source of the suspend request.</param>
|
|
||||||
/// <param name="e">Details about the suspend request.</param>
|
|
||||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
|
||||||
{
|
|
||||||
var deferral = e.SuspendingOperation.GetDeferral();
|
|
||||||
//TODO: Save application state and stop any background activity
|
|
||||||
deferral.Complete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated(IActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Kind == ActivationKind.Protocol)
|
||||||
|
{
|
||||||
|
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
|
||||||
|
var publisher = Mvx.IoCProvider.Resolve<ITokenPublisherService>();
|
||||||
|
publisher.ReceiveToken(eventArgs.Uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
19
SpotifyAPI.Web.Examples/Example.UWP/CoreApp.cs
Normal file
19
SpotifyAPI.Web.Examples/Example.UWP/CoreApp.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Example.UWP.ViewModels;
|
||||||
|
using MvvmCross.IoC;
|
||||||
|
using MvvmCross.ViewModels;
|
||||||
|
|
||||||
|
namespace Example.UWP
|
||||||
|
{
|
||||||
|
public class CoreApp : MvxApplication
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
CreatableTypes()
|
||||||
|
.EndingWith("Service")
|
||||||
|
.AsInterfaces()
|
||||||
|
.RegisterAsLazySingleton();
|
||||||
|
|
||||||
|
RegisterAppStart<LoginViewModel>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,11 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
<ProjectGuid>{8968B88F-3A6B-4012-8449-B502C7CD658A}</ProjectGuid>
|
<ProjectGuid>{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}</ProjectGuid>
|
||||||
<OutputType>AppContainerExe</OutputType>
|
<OutputType>AppContainerExe</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>UWP</RootNamespace>
|
<RootNamespace>Example.UWP</RootNamespace>
|
||||||
<AssemblyName>UWP</AssemblyName>
|
<AssemblyName>Example.UWP</AssemblyName>
|
||||||
<DefaultLanguage>en-US</DefaultLanguage>
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.18362.0</TargetPlatformVersion>
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.18362.0</TargetPlatformVersion>
|
||||||
@ -119,10 +119,17 @@
|
|||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="MainPage.xaml.cs">
|
<Compile Include="CoreApp.cs" />
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="TokenPublisherService.cs" />
|
||||||
|
<Compile Include="ViewModels\LoginViewModel.cs" />
|
||||||
|
<Compile Include="ViewModels\PlaylistsListViewModel.cs" />
|
||||||
|
<Compile Include="Views\LoginView.xaml.cs">
|
||||||
|
<DependentUpon>LoginView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Views\PlaylistsListView.xaml.cs">
|
||||||
|
<DependentUpon>PlaylistsListView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
@ -144,15 +151,30 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
<Page Include="MainPage.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||||
<Version>6.2.9</Version>
|
<Version>6.2.9</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="MvvmCross">
|
||||||
|
<Version>6.4.2</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="Views\LoginView.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Views\PlaylistsListView.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\SpotifyAPI.Web\SpotifyAPI.Web.csproj">
|
||||||
|
<Project>{ec8a93ba-27c4-4642-b7a0-11b809c35be4}</Project>
|
||||||
|
<Name>SpotifyAPI.Web</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<Page
|
|
||||||
x:Class="UWP.MainPage"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:UWP"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
</Page>
|
|
@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
|
||||||
|
|
||||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
|
||||||
|
|
||||||
namespace Example.UWP
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class MainPage : Page
|
|
||||||
{
|
|
||||||
public MainPage()
|
|
||||||
{
|
|
||||||
this.InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,14 +7,14 @@
|
|||||||
IgnorableNamespaces="uap mp">
|
IgnorableNamespaces="uap mp">
|
||||||
|
|
||||||
<Identity
|
<Identity
|
||||||
Name="ca23f8da-8ef6-406e-8234-ba506f52edc2"
|
Name="ad405b02-e8d1-4972-9f4c-d0741ac5f355"
|
||||||
Publisher="CN=jonas"
|
Publisher="CN=jonas"
|
||||||
Version="1.0.0.0" />
|
Version="1.0.0.0" />
|
||||||
|
|
||||||
<mp:PhoneIdentity PhoneProductId="ca23f8da-8ef6-406e-8234-ba506f52edc2" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
<mp:PhoneIdentity PhoneProductId="ad405b02-e8d1-4972-9f4c-d0741ac5f355" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>UWP</DisplayName>
|
<DisplayName>Example.UWP</DisplayName>
|
||||||
<PublisherDisplayName>jonas</PublisherDisplayName>
|
<PublisherDisplayName>jonas</PublisherDisplayName>
|
||||||
<Logo>Assets\StoreLogo.png</Logo>
|
<Logo>Assets\StoreLogo.png</Logo>
|
||||||
</Properties>
|
</Properties>
|
||||||
@ -35,11 +35,19 @@
|
|||||||
DisplayName="Example.UWP"
|
DisplayName="Example.UWP"
|
||||||
Square150x150Logo="Assets\Square150x150Logo.png"
|
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||||
Square44x44Logo="Assets\Square44x44Logo.png"
|
Square44x44Logo="Assets\Square44x44Logo.png"
|
||||||
Description="UWP"
|
Description="Example.UWP"
|
||||||
BackgroundColor="transparent">
|
BackgroundColor="transparent">
|
||||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
|
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
|
||||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||||
</uap:VisualElements>
|
</uap:VisualElements>
|
||||||
|
<Extensions>
|
||||||
|
<uap:Extension Category="windows.protocol">
|
||||||
|
<uap:Protocol Name="spotifyapi.web.oauth">
|
||||||
|
<uap:Logo>Assets\StoreLogo.png</uap:Logo>
|
||||||
|
<uap:DisplayName>SpotifyAPI.Example.UWP</uap:DisplayName>
|
||||||
|
</uap:Protocol>
|
||||||
|
</uap:Extension>
|
||||||
|
</Extensions>
|
||||||
</Application>
|
</Application>
|
||||||
</Applications>
|
</Applications>
|
||||||
|
|
||||||
|
@ -5,11 +5,11 @@ using System.Runtime.InteropServices;
|
|||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("UWP")]
|
[assembly: AssemblyTitle("Example.UWP")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("UWP")]
|
[assembly: AssemblyProduct("Example.UWP")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
36
SpotifyAPI.Web.Examples/Example.UWP/TokenPublisherService.cs
Normal file
36
SpotifyAPI.Web.Examples/Example.UWP/TokenPublisherService.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Example.UWP
|
||||||
|
{
|
||||||
|
public interface ITokenPublisherService
|
||||||
|
{
|
||||||
|
event EventHandler<string> TokenReceived;
|
||||||
|
void ReceiveToken(Uri uri);
|
||||||
|
}
|
||||||
|
public class TokenPublisherService : ITokenPublisherService
|
||||||
|
{
|
||||||
|
public event EventHandler<string> TokenReceived;
|
||||||
|
|
||||||
|
public void ReceiveToken(Uri uri)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(uri.Fragment))
|
||||||
|
{
|
||||||
|
throw new Exception($"Received weird URI: {uri}");
|
||||||
|
}
|
||||||
|
var arguments = uri.Fragment.Substring(1).Split("&")
|
||||||
|
.Select(param => param.Split("="))
|
||||||
|
.ToDictionary(param => param[0], param => param[1]);
|
||||||
|
|
||||||
|
if(arguments["access_token"] == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"No access token found in URI: {uri}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenReceived?.Invoke(this, arguments["access_token"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MvvmCross.Commands;
|
||||||
|
using MvvmCross.Navigation;
|
||||||
|
using MvvmCross.ViewModels;
|
||||||
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
|
namespace Example.UWP.ViewModels
|
||||||
|
{
|
||||||
|
public class LoginViewModel : MvxViewModel, IDisposable
|
||||||
|
{
|
||||||
|
public LoginViewModel(ITokenPublisherService tokenPublisher, IMvxNavigationService navigation)
|
||||||
|
{
|
||||||
|
_tokenPublisher = tokenPublisher;
|
||||||
|
_navigation = navigation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ViewAppeared()
|
||||||
|
{
|
||||||
|
base.ViewAppeared();
|
||||||
|
_tokenPublisher.TokenReceived += TokenPublisher_TokenReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ViewDisappeared()
|
||||||
|
{
|
||||||
|
base.ViewDisappeared();
|
||||||
|
_tokenPublisher.TokenReceived -= TokenPublisher_TokenReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_tokenPublisher.TokenReceived -= TokenPublisher_TokenReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ITokenPublisherService _tokenPublisher;
|
||||||
|
private readonly IMvxNavigationService _navigation;
|
||||||
|
|
||||||
|
private string _titleText = "Spotify OAuth2 Login";
|
||||||
|
public string TitleText
|
||||||
|
{
|
||||||
|
get => _titleText;
|
||||||
|
set => SetProperty(ref _titleText, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Uri _redirectUri = new Uri("spotifyapi.web.oauth://token");
|
||||||
|
public Uri RedirectUri
|
||||||
|
{
|
||||||
|
get => _redirectUri;
|
||||||
|
set => SetProperty(ref _redirectUri, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _clientId = "";
|
||||||
|
public string ClientId
|
||||||
|
{
|
||||||
|
get => _clientId;
|
||||||
|
set {
|
||||||
|
if(SetProperty(ref _clientId, value))
|
||||||
|
{
|
||||||
|
OpenAuthenticationPage.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MvxCommand _openAuthenticationPage;
|
||||||
|
public MvxCommand OpenAuthenticationPage => _openAuthenticationPage ?? (_openAuthenticationPage =
|
||||||
|
new MvxCommand(
|
||||||
|
async () => await DoOpenAuthenticationPage(),
|
||||||
|
() => !string.IsNullOrEmpty(ClientId)
|
||||||
|
));
|
||||||
|
|
||||||
|
public async Task DoOpenAuthenticationPage()
|
||||||
|
{
|
||||||
|
var request = new LoginRequest(new Uri("spotifyapi.web.oauth://token"), ClientId, LoginRequest.ResponseType.Token);
|
||||||
|
await Windows.System.Launcher.LaunchUriAsync(request.ToUri());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TokenPublisher_TokenReceived(object sender, string token)
|
||||||
|
{
|
||||||
|
_navigation.Navigate<PlaylistsListViewModel, string>(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MvvmCross.ViewModels;
|
||||||
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
|
namespace Example.UWP.ViewModels
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Spotify Token is the parameter
|
||||||
|
/// </summary>
|
||||||
|
public class PlaylistsListViewModel : MvxViewModel<string>
|
||||||
|
{
|
||||||
|
private SpotifyClient _spotify;
|
||||||
|
|
||||||
|
private List<SimplePlaylist> _playlists;
|
||||||
|
public List<SimplePlaylist> Playlists {
|
||||||
|
get => _playlists ?? (_playlists = new List<SimplePlaylist>());
|
||||||
|
set => SetProperty(ref _playlists, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Prepare(string token)
|
||||||
|
{
|
||||||
|
_spotify = new SpotifyClient(SpotifyClientConfig.CreateDefault(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Initialize()
|
||||||
|
{
|
||||||
|
await base.Initialize();
|
||||||
|
|
||||||
|
Playlists = await _spotify.Paginate(() => _spotify.Playlists.CurrentUsers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
SpotifyAPI.Web.Examples/Example.UWP/Views/LoginView.xaml
Normal file
71
SpotifyAPI.Web.Examples/Example.UWP/Views/LoginView.xaml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<app:LoginViewPage x:Class="Example.UWP.Views.LoginView"
|
||||||
|
d:DataContext="{d:DesignInstance Type=models:LoginViewModel, IsDesignTimeCreatable=True}"
|
||||||
|
xmlns:app="using:Example.UWP.Views"
|
||||||
|
xmlns:models="using:Example.UWP.ViewModels"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid Background="#353b48">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock Margin="0,50"
|
||||||
|
Grid.Row="0"
|
||||||
|
TextAlignment="Center"
|
||||||
|
Text="{Binding TitleText}"
|
||||||
|
FontSize="45" />
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
Text="Redirect URI:"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Margin="50,20"
|
||||||
|
FontSize="25"
|
||||||
|
HorizontalAlignment="Center" />
|
||||||
|
<TextBox Grid.Column="1"
|
||||||
|
Grid.Row="0"
|
||||||
|
Margin="20"
|
||||||
|
Text="{Binding RedirectUri, Mode=OneWay}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
FontSize="25"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Top" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Grid.Row="1"
|
||||||
|
Text="Spotify Client ID:"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Margin="50,20"
|
||||||
|
FontSize="25"
|
||||||
|
HorizontalAlignment="Center" />
|
||||||
|
<TextBox Grid.Column="1"
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="20"
|
||||||
|
FontSize="25"
|
||||||
|
Text="{Binding ClientId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Top" />
|
||||||
|
</Grid>
|
||||||
|
<Button Grid.Row="2"
|
||||||
|
Command="{Binding OpenAuthenticationPage}"
|
||||||
|
Background="#1db954"
|
||||||
|
FontSize="25"
|
||||||
|
Padding="50,20"
|
||||||
|
HorizontalAlignment="Center">
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</app:LoginViewPage>
|
26
SpotifyAPI.Web.Examples/Example.UWP/Views/LoginView.xaml.cs
Normal file
26
SpotifyAPI.Web.Examples/Example.UWP/Views/LoginView.xaml.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Example.UWP.ViewModels;
|
||||||
|
using MvvmCross.Platforms.Uap.Presenters.Attributes;
|
||||||
|
using MvvmCross.Platforms.Uap.Views;
|
||||||
|
using MvvmCross.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace Example.UWP.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
[MvxViewFor(typeof(LoginViewModel))]
|
||||||
|
[MvxPagePresentation]
|
||||||
|
public sealed partial class LoginView : LoginViewPage
|
||||||
|
{
|
||||||
|
public LoginView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class LoginViewPage : MvxWindowsPage<LoginViewModel>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<app:PlaylistsListViewPage x:Class="Example.UWP.Views.PlaylistsListView"
|
||||||
|
d:DataContext="{d:DesignInstance Type=models:PlaylistsListViewModel, IsDesignTimeCreatable=False}"
|
||||||
|
xmlns:app="using:Example.UWP.Views"
|
||||||
|
xmlns:models="using:Example.UWP.ViewModels"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<ListView x:Name="FruitsList"
|
||||||
|
Background="#353b48"
|
||||||
|
ItemsSource="{Binding Playlists}">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Image Grid.Column="0" Margin="20">
|
||||||
|
<Image.Source>
|
||||||
|
<BitmapImage UriSource="{Binding Images[0].Url}" />
|
||||||
|
</Image.Source>
|
||||||
|
</Image>
|
||||||
|
|
||||||
|
<TextBlock Text="{Binding Name}"
|
||||||
|
Margin="20"
|
||||||
|
FontSize="30"
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</app:PlaylistsListViewPage>
|
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using Example.UWP.ViewModels;
|
||||||
|
using MvvmCross.Platforms.Uap.Presenters.Attributes;
|
||||||
|
using MvvmCross.Platforms.Uap.Views;
|
||||||
|
using MvvmCross.ViewModels;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace Example.UWP.Views
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
[MvxViewFor(typeof(PlaylistsListViewModel))]
|
||||||
|
[MvxPagePresentation]
|
||||||
|
public sealed partial class PlaylistsListView : PlaylistsListViewPage
|
||||||
|
{
|
||||||
|
public PlaylistsListView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class PlaylistsListViewPage : MvxWindowsPage<PlaylistsListViewModel>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
55
SpotifyAPI.Web/Models/Request/LoginRequest.cs
Normal file
55
SpotifyAPI.Web/Models/Request/LoginRequest.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace SpotifyAPI.Web
|
||||||
|
{
|
||||||
|
public class LoginRequest
|
||||||
|
{
|
||||||
|
public LoginRequest(Uri redirectUri, string clientId, ResponseType responseType)
|
||||||
|
{
|
||||||
|
Ensure.ArgumentNotNull(redirectUri, nameof(redirectUri));
|
||||||
|
Ensure.ArgumentNotNullOrEmptyString(clientId, nameof(clientId));
|
||||||
|
|
||||||
|
RedirectUri = redirectUri;
|
||||||
|
ClientId = clientId;
|
||||||
|
ResponseTypeParam = responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri RedirectUri { get; }
|
||||||
|
public ResponseType ResponseTypeParam { get; }
|
||||||
|
public string ClientId { get; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public ICollection<string> Scope { get; set; }
|
||||||
|
public bool? ShowDialog { get; set; }
|
||||||
|
|
||||||
|
public Uri ToUri()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder(SpotifyUrls.Authorize.ToString());
|
||||||
|
builder.Append($"?client_id={ClientId}");
|
||||||
|
builder.Append($"&response_type={ResponseTypeParam.ToString().ToLower()}");
|
||||||
|
builder.Append($"&redirect_uri={HttpUtility.UrlEncode(RedirectUri.ToString())}");
|
||||||
|
if (!string.IsNullOrEmpty(State))
|
||||||
|
{
|
||||||
|
builder.Append($"&state={HttpUtility.UrlEncode(State)}");
|
||||||
|
}
|
||||||
|
if (Scope != null)
|
||||||
|
{
|
||||||
|
builder.Append($"&scope={HttpUtility.UrlEncode(string.Join(" ", Scope))}");
|
||||||
|
}
|
||||||
|
if (ShowDialog != null)
|
||||||
|
{
|
||||||
|
builder.Append($"&show_dialog={ShowDialog.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Uri(builder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ResponseType
|
||||||
|
{
|
||||||
|
Code,
|
||||||
|
Token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.UWP", "SpotifyAPI.Web.Examples\Example.UWP\Example.UWP.csproj", "{8968B88F-3A6B-4012-8449-B502C7CD658A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.UWP", "SpotifyAPI.Web.Examples\Example.UWP\Example.UWP.csproj", "{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -136,32 +136,32 @@ Global
|
|||||||
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x64.Build.0 = Release|Any CPU
|
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x86.ActiveCfg = Release|Any CPU
|
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x86.Build.0 = Release|Any CPU
|
{941AB88D-B3A9-407F-BF88-BFE14B401687}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|Any CPU.ActiveCfg = Debug|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM.ActiveCfg = Debug|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM.Build.0 = Debug|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM.Deploy.0 = Debug|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM64.Build.0 = Debug|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x64.ActiveCfg = Debug|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x64.Build.0 = Debug|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x64.Build.0 = Debug|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x64.Deploy.0 = Debug|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x64.Deploy.0 = Debug|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x86.ActiveCfg = Debug|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x86.Build.0 = Debug|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x86.Build.0 = Debug|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Debug|x86.Deploy.0 = Debug|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Debug|x86.Deploy.0 = Debug|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|Any CPU.ActiveCfg = Release|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM.ActiveCfg = Release|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM.Build.0 = Release|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM.Build.0 = Release|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM.Deploy.0 = Release|ARM
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM.Deploy.0 = Release|ARM
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM64.ActiveCfg = Release|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM64.Build.0 = Release|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|ARM64.Deploy.0 = Release|ARM64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x64.ActiveCfg = Release|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x64.ActiveCfg = Release|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x64.Build.0 = Release|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x64.Build.0 = Release|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x64.Deploy.0 = Release|x64
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x64.Deploy.0 = Release|x64
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x86.ActiveCfg = Release|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x86.ActiveCfg = Release|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x86.Build.0 = Release|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x86.Build.0 = Release|x86
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A}.Release|x86.Deploy.0 = Release|x86
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70}.Release|x86.Deploy.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -169,7 +169,7 @@ Global
|
|||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{F4ECE937-99F2-4C4F-9F5C-4AB875D9538A} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
{F4ECE937-99F2-4C4F-9F5C-4AB875D9538A} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
||||||
{941AB88D-B3A9-407F-BF88-BFE14B401687} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
{941AB88D-B3A9-407F-BF88-BFE14B401687} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
||||||
{8968B88F-3A6B-4012-8449-B502C7CD658A} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
{70D529B5-CEC0-4D3D-B50D-8ECF921DEC70} = {48A7DE65-29BB-409C-AC45-77F6586C0B15}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {097062B8-0E87-43C8-BD98-61843A68BE6D}
|
SolutionGuid = {097062B8-0E87-43C8-BD98-61843A68BE6D}
|
||||||
|
Loading…
Reference in New Issue
Block a user