-
Notifications
You must be signed in to change notification settings - Fork 288
App Center Integration #234
base: master
Are you sure you want to change the base?
Changes from all commits
70e717b
e3b3f9d
7bfdaa0
a8eae3e
858b069
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<ContentDialog | ||
x:Class="HoloLensCommander.MobileCenterAppsDialog" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:HoloLensCommander" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
mc:Ignorable="d" | ||
Title="Mobile Center Apps" | ||
PrimaryButtonText="Close" | ||
PrimaryButtonClick="ContentDialog_PrimaryButtonClick" | ||
MaxHeight="800"> | ||
|
||
<StackPanel> | ||
<Canvas | ||
Width="450" Height="40"> | ||
<TextBlock | ||
x:Name="UserDisplayNameLabel" | ||
Text="Display Name" | ||
FontSize="16" | ||
Canvas.Top="10"/> | ||
<TextBlock | ||
x:Name="UserDisplayName" | ||
Text="{Binding Path=DeviceAddress}" | ||
ToolTipService.ToolTip="The address of the target device" | ||
FontSize="16" | ||
Width="347" | ||
Canvas.Left="103" Canvas.Top="10"/> | ||
</Canvas> | ||
<Canvas | ||
Width="450" Height="440"> | ||
<TextBlock | ||
x:Name="UserEmailLabel" | ||
Text="Email" | ||
FontSize="16"/> | ||
<ListBox | ||
x:Name="MobileCenterAppsList" | ||
ItemsSource="{Binding MobileCenterApps}" | ||
SelectedItem="{Binding SelectedMobileCenterApp, Mode=TwoWay}" | ||
ToolTipService.ToolTip="Mobile Center apps from your organization" | ||
Width="395" Height= "400" | ||
BorderThickness="1" | ||
ScrollViewer.HorizontalScrollMode="Auto" | ||
ScrollViewer.HorizontalScrollBarVisibility="Auto" | ||
Canvas.Top="26"/> | ||
<Button | ||
x:Name="downloadSelectedApp" | ||
Content="" | ||
Command="{Binding DownloadInstallMobileAppsCommand}" | ||
ToolTipService.ToolTip="Download and install selected app from the Mobile Center" | ||
FontFamily="Segoe MDL2 Assets" FontSize="24" | ||
Width="50" Height="40" | ||
Canvas.Left="400" Canvas.Top="25"/> | ||
</Canvas> | ||
</StackPanel> | ||
</ContentDialog> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.InteropServices.WindowsRuntime; | ||
using System.Threading.Tasks; | ||
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; | ||
using Windows.Web.Http; | ||
using Windows.Web.Http.Headers; | ||
using Windows.Web.Http.Filters; | ||
|
||
// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public sealed partial class MobileCenterAppsDialog : ContentDialog | ||
{ | ||
public MobileCenterAppsDialog(AppResponse[] appResponse) | ||
{ | ||
this.DataContext = new MobileCenterAppsDialogViewModel(appResponse); | ||
this.InitializeComponent(); | ||
} | ||
|
||
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) | ||
{ | ||
//close the dialog | ||
} | ||
|
||
private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no secondary button in the XAML, no need to have this method. |
||
{ | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Newtonsoft.Json; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, this project's only dependency is on WindowsDevicePortalWrapper. Is the json data from the app center complex enough to warrant using the Netwtonsoft component? If not, I would prefer we not take an additional dependency. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can help with the deserialization code if we can avoid the component,. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @davidkline-ms Yes, there are only 2 instances of deserializing the JSON response data, and it’s a relatively simple object (~15 fields total, but I only use 4). Help with this would be awesome so that we do not add more dependencies. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. Since you only use the four, we should be able to only define the subset when configuring the object for the built in json serializer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @davidkline-ms what's the easiest way to write our own json parser for these objects? Are you thinking we parse the strings ourselves? Or are there built in functions I am not aware of? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here is a sample class definition from the WindowsDevicePortalWrapper project:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file shows how WDPW validates and handles the JSON. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the BatteryState example, if all you cared about was whether or not a battery existed and if the system was plugged in, you could include only the first two members of the class. |
||
using System.ComponentModel; | ||
using System.Net; | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public partial class MobileCenterAppsDialogViewModel : INotifyPropertyChanged | ||
{ | ||
public event PropertyChangedEventHandler PropertyChanged; | ||
|
||
public MobileCenterAppsDialogViewModel (AppResponse[] appResponseList) | ||
{ | ||
for (int i = 0; i < appResponseList.Length; i++) | ||
{ | ||
this.MobileCenterApps.Add(appResponseList[i].name); | ||
} | ||
|
||
//Register the commands for the mobile center apps dialog | ||
this.DownloadInstallMobileAppsCommand = new Command( | ||
async (parameter) => | ||
{ | ||
await this.DownloadInstallMobileAppsAsync(appResponseList); | ||
}); | ||
} | ||
private void NotifyPropertyChanged(string propertyName) | ||
{ | ||
this.PropertyChanged?.Invoke( | ||
this, | ||
new PropertyChangedEventArgs(propertyName)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System.Windows.Input; | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public partial class MobileCenterAppsDialogViewModel | ||
{ | ||
AppCenterWebRequest appCenterWebRequest = new AppCenterWebRequest(); | ||
public ICommand DownloadInstallMobileAppsCommand | ||
{ get; private set; } | ||
|
||
private async Task DownloadInstallMobileAppsAsync(AppResponse[] appList) | ||
{ | ||
string selectedApp = this.SelectedMobileCenterApp as string; | ||
DownloadResponse downloadResponse; | ||
|
||
for (int i = 0; i < appList.Length; i++) | ||
{ | ||
if (selectedApp == appList[i].name || selectedApp == appList[i].display_name) | ||
{ | ||
string requestResponseJson = await appCenterWebRequest.HttpReleaseRequest(appList[i].app_secret); | ||
downloadResponse = JsonConvert.DeserializeObject<DownloadResponse>(requestResponseJson); | ||
appCenterWebRequest.HttpDownloadRequest(downloadResponse.download_url, selectedApp); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public partial class MobileCenterAppsDialogViewModel | ||
{ | ||
private List<string> mobileCenterApps = new List<string>(); | ||
public List<string> MobileCenterApps | ||
{ | ||
get | ||
{ | ||
return this.mobileCenterApps; | ||
} | ||
set | ||
{ | ||
if (this.mobileCenterApps != value) | ||
{ | ||
this.mobileCenterApps = value; | ||
this.NotifyPropertyChanged(nameof(MobileCenterApps)); | ||
} | ||
} | ||
} | ||
|
||
private string selectedMobileCenterApp = string.Empty; | ||
public string SelectedMobileCenterApp | ||
{ | ||
get | ||
{ | ||
return this.selectedMobileCenterApp; | ||
} | ||
set | ||
{ | ||
if (this.selectedMobileCenterApp!=value) | ||
{ | ||
this.selectedMobileCenterApp = value; | ||
this.NotifyPropertyChanged(nameof(SelectedMobileCenterApp)); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<ContentDialog | ||
x:Class="HoloLensCommander.SetAPItokenDialog" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:HoloLensCommander" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
mc:Ignorable="d" | ||
Title="Set API Token" | ||
PrimaryButtonText="Ok" | ||
SecondaryButtonText="Cancel" | ||
PrimaryButtonClick="ContentDialog_PrimaryButtonClick" | ||
SecondaryButtonClick="ContentDialog_SecondaryButtonClick"> | ||
|
||
<StackPanel> | ||
<Canvas | ||
Width="350" Height="50"> | ||
<TextBlock | ||
x:Name="TokenLabel" | ||
Text="Token" | ||
FontSize="16" | ||
Canvas.Top="16" Canvas.Left="5"/> | ||
<TextBox | ||
x:Name="token" | ||
Text="{Binding Path= APIToken, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" | ||
ToolTipService.ToolTip="Mobile Center API Token" | ||
Width="200" | ||
Canvas.Top="10" Canvas.Left="85"/> | ||
</Canvas> | ||
<Canvas | ||
Width="350" Height="50"> | ||
<TextBlock | ||
x:Name="Password" | ||
Text="Password" | ||
FontSize="16" | ||
Canvas.Top="16" Canvas.Left="5"/> | ||
<TextBox | ||
x:Name="password" | ||
Text="{Binding Path= AppCenterPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" | ||
ToolTipService.ToolTip="Mobile Center API Token" | ||
Width="200" | ||
Canvas.Top="10" Canvas.Left="85"/> | ||
</Canvas> | ||
<Canvas | ||
Width="350" Height="50"> | ||
<TextBlock | ||
x:Name="UserName" | ||
Text="User" | ||
FontSize="16" | ||
Canvas.Top="16" Canvas.Left="5"/> | ||
<TextBox | ||
x:Name="username" | ||
Text="{Binding Path= AppCenterUserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" | ||
ToolTipService.ToolTip="Mobile Center UserName" | ||
Width="200" | ||
Canvas.Top="10" Canvas.Left="85"/> | ||
</Canvas> | ||
</StackPanel> | ||
</ContentDialog> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Net; | ||
using Windows.UI.Xaml.Controls; | ||
|
||
// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public sealed partial class SetAPItokenDialog : ContentDialog | ||
{ | ||
private UserToken apiToken; | ||
private NetworkCredential appCenterCredentials; | ||
|
||
public SetAPItokenDialog(UserToken APItoken, NetworkCredential AppCenterCredentials) | ||
{ | ||
this.apiToken = APItoken; | ||
this.appCenterCredentials = AppCenterCredentials; | ||
this.DataContext = new SetAPItokenDialogViewModel(APItoken, AppCenterCredentials); | ||
this.InitializeComponent(); | ||
} | ||
|
||
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) | ||
{ | ||
((SetAPItokenDialogViewModel)this.DataContext).UpdateAPItoken(this.apiToken); | ||
((SetAPItokenDialogViewModel)this.DataContext).UpdateAppCenterCredentials(this.appCenterCredentials); | ||
} | ||
|
||
private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) | ||
{ | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace HoloLensCommander | ||
{ | ||
public partial class SetAPItokenDialogViewModel : INotifyPropertyChanged | ||
{ | ||
/// <summary> | ||
/// Event that is notified when a property value has changed. | ||
/// </summary> | ||
public event PropertyChangedEventHandler PropertyChanged; | ||
|
||
public SetAPItokenDialogViewModel(UserToken apiToken, NetworkCredential appCenterCredentials) | ||
{ | ||
this.APIToken= apiToken.ApiToken; | ||
this.AppCenterUserName = appCenterCredentials.UserName; | ||
this.AppCenterPassword = appCenterCredentials.Password; | ||
} | ||
|
||
/// <summary> | ||
/// Sends the PropertyChanged events to registered handlers. | ||
/// </summary> | ||
/// <param name="propertyName">The name of property that has changed.</param> | ||
private void NotifyPropertyChanged(string propertyName) | ||
{ | ||
this.PropertyChanged?.Invoke( | ||
this, | ||
new PropertyChangedEventArgs(propertyName)); | ||
} | ||
|
||
internal void UpdateAPItoken(UserToken apiToken) | ||
{ | ||
apiToken.ApiToken = this.APIToken; | ||
} | ||
|
||
internal void UpdateAppCenterCredentials(NetworkCredential appCenterCredentials) | ||
{ | ||
appCenterCredentials.UserName = this.AppCenterUserName; | ||
appCenterCredentials.Password = this.AppCenterPassword; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to make this multi-select?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davidkline-ms Yes, we could make it multi-select to allow for multiple downloads at once. That would require some additional steps for making the download call async and queuing up concurrent downloads, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are probably right. Unless the AppCenter has an endpoint for "install these". Probably something best left for the next rev :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my knowledge there is not. I am using the download URL and then caching that downloaded data. There is "install" api other than to install to a mobile device for testing.