This commit is contained in:
ridomin 2017-04-25 18:20:09 -07:00
Родитель 9171d5a171
Коммит 7516b3fad5
44 изменённых файлов: 1939 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,11 @@
# top-most EditorConfig file
root = true
[*]
end_of_line = crlf
[*.{cs,xaml}]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

Просмотреть файл

@ -0,0 +1,30 @@
using System.Threading.Tasks;
namespace RidoShop.Client.Activation
{
internal abstract class ActivationHandler
{
public abstract bool CanHandle(object args);
public abstract Task HandleAsync(object args);
}
internal abstract class ActivationHandler<T> : ActivationHandler where T : class
{
protected abstract Task HandleInternalAsync(T args);
public override async Task HandleAsync(object args)
{
await HandleInternalAsync(args as T);
}
public override bool CanHandle(object args)
{
return args is T && CanHandleInternal(args as T);
}
protected virtual bool CanHandleInternal(T args)
{
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
using System;
using System.Threading.Tasks;
using RidoShop.Client.Services;
using Windows.ApplicationModel.Activation;
namespace RidoShop.Client.Activation
{
internal class DefaultLaunchActivationHandler : ActivationHandler<LaunchActivatedEventArgs>
{
private readonly Type _navElement;
public DefaultLaunchActivationHandler(Type navElement)
{
_navElement = navElement;
}
protected override async Task HandleInternalAsync(LaunchActivatedEventArgs args)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
NavigationService.Navigate(_navElement, args.Arguments);
await Task.CompletedTask;
}
protected override bool CanHandleInternal(LaunchActivatedEventArgs args)
{
// None of the ActivationHandlers has handled the app activation
return NavigationService.Frame.Content == null;
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
<Application
x:Class="RidoShop.Client.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
</ResourceDictionary>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using RidoShop.Client.Services;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
namespace RidoShop.Client
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
private Lazy<ActivationService> _activationService;
private ActivationService ActivationService { get { return _activationService.Value; } }
/// <summary>
/// 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()
{
InitializeComponent();
EnteredBackground += App_EnteredBackground;
//Deferred execution until used. Check https://msdn.microsoft.com/library/dd642331(v=vs.110).aspx for further info on Lazy<T> class.
_activationService = new Lazy<ActivationService>(CreateActivationService);
}
/// <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 async void OnLaunched(LaunchActivatedEventArgs e)
{
if (!e.PrelaunchActivated)
{
await ActivationService.ActivateAsync(e);
}
}
/// <summary>
/// Invoked when the application is activated by some means other than normal launching.
/// </summary>
/// <param name="args">Event data for the event.</param>
protected override async void OnActivated(IActivatedEventArgs args)
{
await ActivationService.ActivateAsync(args);
}
private async void App_EnteredBackground(object sender, EnteredBackgroundEventArgs e)
{
var deferral = e.GetDeferral();
await Helpers.Singleton<SuspendAndResumeService>.Instance.SaveStateAsync();
deferral.Complete();
}
private ActivationService CreateActivationService()
{
return new ActivationService(this, typeof(Views.MainPage), new Views.ShellPage());
}
}
}

Двоичные данные
RidoShop.Core/RidoShop.Client/Assets/LockScreenLogo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
RidoShop.Core/RidoShop.Client/Assets/SplashScreen.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.9 KiB

Двоичные данные
RidoShop.Core/RidoShop.Client/Assets/Square44x44Logo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
RidoShop.Core/RidoShop.Client/Assets/StoreLogo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
RidoShop.Core/RidoShop.Client/Assets/Wide310x150Logo.scale-200.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -0,0 +1,25 @@
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace RidoShop.Client.Helpers
{
public static class Json
{
public static async Task<T> ToObjectAsync<T>(string value)
{
return await Task.Run<T>(() =>
{
return JsonConvert.DeserializeObject<T>(value);
});
}
public static async Task<string> StringifyAsync(object value)
{
return await Task.Run<string>(() =>
{
return JsonConvert.SerializeObject(value);
});
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace RidoShop.Client.Helpers
{
public class Observable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

Просмотреть файл

@ -0,0 +1,43 @@
using System;
using System.Windows.Input;
namespace RidoShop.Client.Helpers
{
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute) : this(execute, null) { }
public RelayCommand(Action execute, Func<bool> canExecute)
{
this._execute = execute ?? throw new ArgumentNullException("execute");
this._canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
public void Execute(object parameter) => _execute();
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public class RelayCommand<T> : ICommand
{
private readonly Action<T> _execute;
private readonly Func<T, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action<T> execute) : this(execute, null) { }
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
this._execute = execute ?? throw new ArgumentNullException("execute");
this._canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);
public void Execute(object parameter) => _execute((T)parameter);
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
using Windows.ApplicationModel.Resources;
namespace RidoShop.Client.Helpers
{
internal static class ResourceExtensions
{
public static string GetLocalized(this string resourceKey)
{
return new ResourceLoader().GetString(resourceKey);
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;
namespace RidoShop.Client.Helpers
{
public static class SettingsStorageExtensions
{
// Use this extension methods to store and retrieve in local and roaming app data
// For more info regarding storing and retrieving app data,
// Documentation: https://docs.microsoft.com/windows/uwp/app-settings/store-and-retrieve-app-data
private const string fileExtension = ".json";
public static bool IsRoamingStorageAvailable(this ApplicationData appData)
{
return (appData.RoamingStorageQuota == 0);
}
public static async Task SaveAsync<T>(this StorageFolder folder, string name, T content)
{
var file = await folder.CreateFileAsync(GetFileName(name), CreationCollisionOption.ReplaceExisting);
var fileContent = await Json.StringifyAsync(content);
await FileIO.WriteTextAsync(file, fileContent);
}
public static async Task<T> ReadAsync<T>(this StorageFolder folder, string name)
{
if (!File.Exists(Path.Combine(folder.Path, GetFileName(name))))
{
return default(T);
}
var file = await folder.GetFileAsync($"{name}.json");
var fileContent = await FileIO.ReadTextAsync(file);
return await Json.ToObjectAsync<T>(fileContent);
}
public static async Task SaveAsync<T>(this ApplicationDataContainer settings, string key, T value)
{
settings.Values[key] = await Json.StringifyAsync(value);
}
public static async Task<T> ReadAsync<T>(this ApplicationDataContainer settings, string key)
{
object obj = null;
if (settings.Values.TryGetValue(key, out obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
return default(T);
}
private static string GetFileName(string name)
{
return string.Concat(name, fileExtension);
}
}
}

Просмотреть файл

@ -0,0 +1,18 @@
using System;
using System.Collections.Concurrent;
namespace RidoShop.Client.Helpers
{
internal static class Singleton<T> where T : new()
{
private static ConcurrentDictionary<Type, T> _instances = new ConcurrentDictionary<Type, T>();
public static T Instance
{
get
{
return _instances.GetOrAdd(typeof(T), (t) => new T());
}
}
}
}

Просмотреть файл

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:genTemplate="http://schemas.microsoft.com/appx/developer/windowsTemplateStudio"
IgnorableNamespaces="uap mp genTemplate">
<Identity
Name="962F189D-3DC1-41B9-918F-4A2F9A950752"
Publisher="CN=rmpablos"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="962F189D-3DC1-41B9-918F-4A2F9A950752" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>RidoShop.Client</DisplayName>
<PublisherDisplayName>rmpablos</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="RidoShop.Client.App">
<uap:VisualElements
DisplayName="RidoShop.Client"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="RidoShop.Client"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
<genTemplate:Metadata>
<genTemplate:Item Name="generator" Value="Windows Template Studio"/>
<genTemplate:Item Name="wizardVersion" Version="0.3.17111.1" />
<genTemplate:Item Name="templatesVersion" Version="0.3.17115.1" />
</genTemplate:Metadata>
</Package>

Просмотреть файл

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RidoShop.Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RidoShop.Client")]
[assembly: AssemblyCopyright("Copyright © 1976")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

Просмотреть файл

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{B94E6806-AB0A-46D7-B93E-DE1674368EA6}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RidoShop.Client</RootNamespace>
<AssemblyName>RidoShop.Client</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.14393.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<PackageCertificateKeyFile>RidoShop.Client_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>5.3.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Uwp.Managed">
<Version>2.0.0</Version>
</PackageReference>
<!-- Nuget package references -->
<PackageReference Include="Newtonsoft.Json">
<Version>10.0.2</Version>
</PackageReference>
<PackageReference Include="WindowsAzure.Messaging.Managed">
<Version>0.1.7.9</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Activation\ActivationHandler.cs" />
<Compile Include="Helpers\Json.cs" />
<Compile Include="Helpers\Observable.cs" />
<Compile Include="Helpers\RelayCommand.cs" />
<Compile Include="Helpers\SettingsStorageExtensions.cs" />
<Compile Include="Services\ActivationService.cs" />
<Compile Include="Activation\DefaultLaunchActivationHandler.cs" />
<Compile Include="Services\HubNotificationsService.cs" />
<Compile Include="Services\NavigationService.cs" />
<Compile Include="Services\OnBackgroundEnteringEventArgs.cs" />
<Compile Include="Services\SuspendAndResumeService.cs" />
<Compile Include="Services\SuspensionState.cs" />
<Compile Include="Services\ThemeSelectorService.cs" />
<Compile Include="ViewModels\InsightsViewModel.cs" />
<Compile Include="ViewModels\MainViewModel.cs" />
<Compile Include="ViewModels\SettingsViewModel.cs" />
<Compile Include="ViewModels\ShellNavigationItem.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="Views\InsightsPage.xaml.cs">
<DependentUpon>InsightsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ShellPage.xaml.cs">
<DependentUpon>ShellPage.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PRIResource Include="Strings\en-us\Resources.resw" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\ResourceExtensions.cs" />
<Compile Include="Helpers\Singleton.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
<None Include="RidoShop.Client_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<ItemGroup>
<Page Include="Views\InsightsPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ShellPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using RidoShop.Client.Activation;
using RidoShop.Client.Helpers;
using Windows.ApplicationModel.Activation;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace RidoShop.Client.Services
{
internal class ActivationService
{
private readonly App _app;
private readonly UIElement _shell;
private readonly Type _defaultNavItem;
public ActivationService(App app, Type defaultNavItem, UIElement shell = null)
{
_app = app;
_shell = shell ?? new Frame();
_defaultNavItem = defaultNavItem;
}
public async Task ActivateAsync(object activationArgs)
{
if (IsInteractive(activationArgs))
{
// Initialize things like registering background task before the app is loaded
await InitializeAsync();
//#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
_app.DebugSettings.EnableFrameRateCounter = true;
}
//#endif
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (Window.Current.Content == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
Window.Current.Content = _shell;
NavigationService.Frame.NavigationFailed += (sender, e) =>
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
};
NavigationService.Frame.Navigated += OnFrameNavigated;
if (SystemNavigationManager.GetForCurrentView() != null)
{
SystemNavigationManager.GetForCurrentView().BackRequested += OnAppViewBackButtonRequested;
}
}
}
var activationHandler = GetActivationHandlers()
.FirstOrDefault(h => h.CanHandle(activationArgs));
if (activationHandler != null)
{
await activationHandler.HandleAsync(activationArgs);
}
if (IsInteractive(activationArgs))
{
var defaultHandler = new DefaultLaunchActivationHandler(_defaultNavItem);
if (defaultHandler.CanHandle(activationArgs))
{
await defaultHandler.HandleAsync(activationArgs);
}
// Ensure the current window is active
Window.Current.Activate();
// Tasks after activation
await StartupAsync();
}
}
private async Task InitializeAsync()
{
await ThemeSelectorService.InitializeAsync();
await Task.CompletedTask;
}
private async Task StartupAsync()
{
//TODO UWPTemplates: To use the HubNotificationService especific data related with your Azure Notification Hubs is required.
// 1. Go to the HubNotificationsService class, in the InitializeAsync() method, provide the Hub Name and DefaultListenSharedAccessSignature.
// 2. Uncomment the following line (an exception is thrown if it is executed before the previous information is provided).
//Singleton<HubNotificationsService>.Instance.InitializeAsync();
Services.ThemeSelectorService.SetRequestedTheme();
await Task.CompletedTask;
}
private IEnumerable<ActivationHandler> GetActivationHandlers()
{
yield return Singleton<SuspendAndResumeService>.Instance;
yield return Singleton<HubNotificationsService>.Instance;
yield break;
}
private bool IsInteractive(object args)
{
return args is IActivatedEventArgs;
}
private void OnFrameNavigated(object sender, NavigationEventArgs e)
{
if (NavigationService.CanGoBack)
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
}
else
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}
}
private void OnAppViewBackButtonRequested(object sender, BackRequestedEventArgs e)
{
if (NavigationService.CanGoBack)
{
NavigationService.GoBack();
e.Handled = true;
}
}
}
}

Просмотреть файл

@ -0,0 +1,47 @@
using System;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Messaging;
using RidoShop.Client.Activation;
using Windows.ApplicationModel.Activation;
using Windows.Networking.PushNotifications;
namespace RidoShop.Client.Services
{
internal class HubNotificationsService : ActivationHandler<ToastNotificationActivatedEventArgs>
{
public async void InitializeAsync()
{
// See more about adding push notifications to your Windows app
// Documentation: https://docs.microsoft.com/azure/app-service-mobile/app-service-mobile-windows-store-dotnet-get-started-push
// Use your Hub Name here
var hubName = "";
// Use your DefaultListenSharedAccessSignature here
var accessSignature = "";
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub(hubName, accessSignature);
var result = await hub.RegisterNativeAsync(channel.Uri);
if (result.RegistrationId != null)
{
// RegistrationID let you know it was successful
}
// You can also send push notifications from Windows Developer Center targeting your app consumers
// Documentation: https://docs.microsoft.com/windows/uwp/publish/send-push-notifications-to-your-apps-customers
}
protected override async Task HandleInternalAsync(ToastNotificationActivatedEventArgs args)
{
// TODO UWPTemplates: Handle activation from toast notification,
// for more info handling activation see
// Documentation: https://blogs.msdn.microsoft.com/tiles_and_toasts/2015/07/08/quickstart-sending-a-local-toast-notification-and-handling-activations-from-it-windows-10/
await Task.CompletedTask;
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
namespace RidoShop.Client.Services
{
public static class NavigationService
{
private static Frame _frame;
public static Frame Frame
{
get
{
if (_frame == null)
{
_frame = Window.Current.Content as Frame;
}
return _frame;
}
set
{
_frame = value;
}
}
public static bool CanGoBack => Frame.CanGoBack;
public static bool CanGoForward => Frame.CanGoForward;
public static void GoBack() => Frame.GoBack();
public static void GoForward() => Frame.GoForward();
public static bool Navigate(Type pageType, object parameter = null, NavigationTransitionInfo infoOverride = null)
{
// Don't open the same page multiple times
if (Frame.Content?.GetType() != pageType)
{
return Frame.Navigate(pageType, parameter, infoOverride);
}
else
{
return false;
}
}
public static bool Navigate<T>(object parameter = null, NavigationTransitionInfo infoOverride = null) where T : Page => Navigate(typeof(T), parameter, infoOverride);
}
}

Просмотреть файл

@ -0,0 +1,16 @@
using System;
namespace RidoShop.Client.Services
{
public class OnBackgroundEnteringEventArgs : EventArgs
{
public SuspensionState SuspensionState { get; set; }
public Type Target { get; private set; }
public OnBackgroundEnteringEventArgs(SuspensionState suspensionState, Type target) : base()
{
SuspensionState = suspensionState;
Target = target;
}
}
}

Просмотреть файл

@ -0,0 +1,58 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using RidoShop.Client.Activation;
using RidoShop.Client.Helpers;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.UI.Xaml.Controls;
namespace RidoShop.Client.Services
{
internal class SuspendAndResumeService : ActivationHandler<LaunchActivatedEventArgs>
{
// TODO UWPTEMPLATES: For more information regarding the application lifecycle and how to handle suspend and resume, please see:
// Documentation: https://docs.microsoft.com/windows/uwp/launch-resume/app-lifecycle
private const string stateFilename = "suspensionState";
// TODO UWPTEMPLATES: This event is fired just before the app enters in background. Subscribe to this event if you want to save your current state.
public event EventHandler<OnBackgroundEnteringEventArgs> OnBackgroundEntering;
public async Task SaveStateAsync()
{
var suspensionState = new SuspensionState()
{
SuspensionDate = DateTime.Now
};
var target = OnBackgroundEntering?.Target.GetType();
var onBackgroundEnteringArgs = new OnBackgroundEnteringEventArgs(suspensionState, target);
OnBackgroundEntering?.Invoke(this, onBackgroundEnteringArgs);
await ApplicationData.Current.LocalFolder.SaveAsync(stateFilename, onBackgroundEnteringArgs);
}
protected override async Task HandleInternalAsync(LaunchActivatedEventArgs args)
{
await RestoreStateAsync();
}
protected override bool CanHandleInternal(LaunchActivatedEventArgs args)
{
return args.PreviousExecutionState == ApplicationExecutionState.Terminated;
}
private async Task RestoreStateAsync()
{
var saveState = await ApplicationData.Current.LocalFolder.ReadAsync<OnBackgroundEnteringEventArgs>(stateFilename);
if (typeof(Page).IsAssignableFrom(saveState?.Target))
{
NavigationService.Navigate(saveState.Target, saveState.SuspensionState);
}
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using System;
namespace RidoShop.Client.Services
{
public class SuspensionState
{
public Object Data { get; set; }
public DateTime SuspensionDate { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,74 @@
using System;
using System.Threading.Tasks;
using RidoShop.Client.Helpers;
using Windows.Storage;
using Windows.UI.Xaml;
namespace RidoShop.Client.Services
{
public static class ThemeSelectorService
{
private const string SettingsKey = "RequestedTheme";
public static event EventHandler<ElementTheme> OnThemeChanged = delegate { };
public static bool IsLightThemeEnabled => Theme == ElementTheme.Light;
public static ElementTheme Theme { get; set; }
public static async Task InitializeAsync()
{
Theme = await LoadThemeFromSettingsAsync();
}
public static async Task SwitchThemeAsync()
{
if (Theme == ElementTheme.Dark)
{
await SetThemeAsync(ElementTheme.Light);
}
else
{
await SetThemeAsync(ElementTheme.Dark);
}
}
public static async Task SetThemeAsync(ElementTheme theme)
{
Theme = theme;
SetRequestedTheme();
await SaveThemeInSettingsAsync(Theme);
}
public static void SetRequestedTheme()
{
var frameworkElement = Window.Current.Content as FrameworkElement;
if (frameworkElement != null)
{
frameworkElement.RequestedTheme = Theme;
OnThemeChanged(null, Theme);
}
}
private static async Task<ElementTheme> LoadThemeFromSettingsAsync()
{
ElementTheme cacheTheme = ElementTheme.Light;
string themeName = await ApplicationData.Current.LocalSettings.ReadAsync<string>(SettingsKey);
if (String.IsNullOrEmpty(themeName))
{
cacheTheme = Application.Current.RequestedTheme == ApplicationTheme.Dark ? ElementTheme.Dark : ElementTheme.Light;
}
else
{
Enum.TryParse<ElementTheme>(themeName, out cacheTheme);
}
return cacheTheme;
}
private static async Task SaveThemeInSettingsAsync(ElementTheme theme)
{
await ApplicationData.Current.LocalSettings.SaveAsync<string>(SettingsKey, theme.ToString());
}
}
}

Просмотреть файл

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Main_Title.Text" xml:space="preserve">
<value>Main</value>
</data>
<data name="Insights_Pivot.Text" xml:space="preserve">
<value>Insights</value>
</data>
<data name="Insights_PivotItem1.Header" xml:space="preserve">
<value>Item 1</value>
</data>
<data name="Insights_PivotItem2.Header" xml:space="preserve">
<value>Item 2</value>
</data>
<data name="Settings_Title.Text" xml:space="preserve">
<value>Settings</value>
</data>
<data name="Settings_Theme.Text" xml:space="preserve">
<value>Theme</value>
</data>
<data name="Settings_Toggle.OnContent" xml:space="preserve">
<value>Light</value>
</data>
<data name="Settings_Toggle.OffContent" xml:space="preserve">
<value>Dark</value>
</data>
<data name="Settings_About.Text" xml:space="preserve">
<value>About this application</value>
</data>
<data name="Settings_AboutDescription.Text" xml:space="preserve">
<value>Lorem ipsum dolor sit</value>
</data>
<data name="Settings_PrivacyTermsLink.Content" xml:space="preserve">
<value>Privacy Terms</value>
</data>
<data name="Settings_PrivacyTermsLink.NavigateUri" xml:space="preserve">
<value>https://YourPrivacyUrlGoesHere/</value>
</data>
NavigateUri
<data name="Shell_Main" xml:space="preserve">
<value>Main</value>
</data>
<data name="Shell_Insights" xml:space="preserve">
<value>Insights</value>
</data>
<data name="Shell_Settings" xml:space="preserve">
<value>Settings</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,13 @@
using System;
using RidoShop.Client.Helpers;
namespace RidoShop.Client.ViewModels
{
public class InsightsViewModel : Observable
{
public InsightsViewModel()
{
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
using RidoShop.Client.Helpers;
namespace RidoShop.Client.ViewModels
{
public class MainViewModel : Observable
{
public MainViewModel()
{
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
using System;
using System.Windows.Input;
using RidoShop.Client.Helpers;
using RidoShop.Client.Services;
using Windows.ApplicationModel;
namespace RidoShop.Client.ViewModels
{
public class SettingsViewModel : Observable
{
// TODO UWPTemplates: Add other settings as necessary. For help see https://github.com/Microsoft/WindowsTemplateStudio/blob/master/docs/pages/settings.md
private bool _isLightThemeEnabled;
public bool IsLightThemeEnabled
{
get { return _isLightThemeEnabled; }
set { Set(ref _isLightThemeEnabled, value); }
}
private string _appDescription;
public string AppDescription
{
get { return _appDescription; }
set { Set(ref _appDescription, value); }
}
public ICommand SwitchThemeCommand { get; private set; }
public SettingsViewModel()
{
IsLightThemeEnabled = ThemeSelectorService.IsLightThemeEnabled;
SwitchThemeCommand = new RelayCommand(async () => { await ThemeSelectorService.SwitchThemeAsync(); });
}
public void Initialize()
{
AppDescription = GetAppDescription();
}
private string GetAppDescription()
{
var package = Package.Current;
var packageId = package.Id;
var version = packageId.Version;
return $"{package.DisplayName} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
}
}
}

Просмотреть файл

@ -0,0 +1,76 @@
using System;
using RidoShop.Client.Helpers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace RidoShop.Client.ViewModels
{
public class ShellNavigationItem : Observable
{
private bool _isSelected;
private Visibility _selectedVis = Visibility.Collapsed;
public Visibility SelectedVis
{
get { return _selectedVis; }
set { Set(ref _selectedVis, value); }
}
private SolidColorBrush _selectedForeground = null;
public SolidColorBrush SelectedForeground
{
get
{
return _selectedForeground ?? (_selectedForeground = GetStandardTextColorBrush());
}
set { Set(ref _selectedForeground, value); }
}
public string Label { get; set; }
public Symbol Symbol { get; set; }
public char SymbolAsChar { get { return (char)Symbol; } }
public Type PageType { get; set; }
public bool IsSelected
{
get { return _isSelected; }
set
{
Set(ref _isSelected, value);
SelectedVis = value ? Visibility.Visible : Visibility.Collapsed;
SelectedForeground = value
? Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush
: GetStandardTextColorBrush();
}
}
private SolidColorBrush GetStandardTextColorBrush()
{
var result = Application.Current.Resources["SystemControlForegroundBaseHighBrush"] as SolidColorBrush;
if (!Services.ThemeSelectorService.IsLightThemeEnabled)
{
result = Application.Current.Resources["SystemControlForegroundAltHighBrush"] as SolidColorBrush;
}
return result;
}
private ShellNavigationItem(string name, Symbol symbol, Type pageType)
{
this.Label = name;
this.Symbol = symbol;
this.PageType = pageType;
Services.ThemeSelectorService.OnThemeChanged += (s, e) => { if (!IsSelected) SelectedForeground = GetStandardTextColorBrush(); };
}
public static ShellNavigationItem FromType<T>(string name, Symbol symbol) where T : Page
{
return new ShellNavigationItem(name, symbol, typeof(T));
}
}
}

Просмотреть файл

@ -0,0 +1,175 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using RidoShop.Client.Helpers;
using RidoShop.Client.Services;
using RidoShop.Client.Views;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace RidoShop.Client.ViewModels
{
public class ShellViewModel : Observable
{
private const string PanoramicStateName = "PanoramicState";
private const string WideStateName = "WideState";
private const string NarrowStateName = "NarrowState";
private bool _isPaneOpen;
public bool IsPaneOpen
{
get { return _isPaneOpen; }
set { Set(ref _isPaneOpen, value); }
}
private SplitViewDisplayMode _displayMode = SplitViewDisplayMode.CompactInline;
public SplitViewDisplayMode DisplayMode
{
get { return _displayMode; }
set { Set(ref _displayMode, value); }
}
private object _lastSelectedItem;
private ObservableCollection<ShellNavigationItem> _primaryItems = new ObservableCollection<ShellNavigationItem>();
public ObservableCollection<ShellNavigationItem> PrimaryItems
{
get { return _primaryItems; }
set { Set(ref _primaryItems, value); }
}
private ObservableCollection<ShellNavigationItem> _secondaryItems = new ObservableCollection<ShellNavigationItem>();
public ObservableCollection<ShellNavigationItem> SecondaryItems
{
get { return _secondaryItems; }
set { Set(ref _secondaryItems, value); }
}
private ICommand _openPaneCommand;
public ICommand OpenPaneCommand
{
get
{
if (_openPaneCommand == null)
{
_openPaneCommand = new RelayCommand(() => IsPaneOpen = !_isPaneOpen);
}
return _openPaneCommand;
}
}
private ICommand _itemSelected;
public ICommand ItemSelectedCommand
{
get
{
if (_itemSelected == null)
{
_itemSelected = new RelayCommand<ShellNavigationItem>(ItemSelected);
}
return _itemSelected;
}
}
private ICommand _stateChangedCommand;
public ICommand StateChangedCommand
{
get
{
if (_stateChangedCommand == null)
{
_stateChangedCommand = new RelayCommand<Windows.UI.Xaml.VisualStateChangedEventArgs>(OnStateChanged);
}
return _stateChangedCommand;
}
}
private void OnStateChanged(VisualStateChangedEventArgs args)
{
if (args.NewState.Name == PanoramicStateName)
{
DisplayMode = SplitViewDisplayMode.CompactInline;
}
else if (args.NewState.Name == WideStateName)
{
DisplayMode = SplitViewDisplayMode.CompactInline;
IsPaneOpen = false;
}
else if (args.NewState.Name == NarrowStateName)
{
DisplayMode = SplitViewDisplayMode.Overlay;
IsPaneOpen = false;
}
}
public void Initialize(Frame frame)
{
NavigationService.Frame = frame;
NavigationService.Frame.Navigated += NavigationService_Navigated;
PopulateNavItems();
}
private void PopulateNavItems()
{
_primaryItems.Clear();
_secondaryItems.Clear();
// More on Segoe UI Symbol icons: https://docs.microsoft.com/windows/uwp/style/segoe-ui-symbol-font
// Edit String/en-US/Resources.resw: Add a menu item title for each page
_primaryItems.Add(ShellNavigationItem.FromType<MainPage>("Shell_Main".GetLocalized(), Symbol.Document));
_primaryItems.Add(ShellNavigationItem.FromType<InsightsPage>("Shell_Insights".GetLocalized(), Symbol.Document));
_secondaryItems.Add(ShellNavigationItem.FromType<SettingsPage>("Shell_Settings".GetLocalized(), Symbol.Document));
}
private void ItemSelected(ShellNavigationItem e)
{
if (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay)
{
IsPaneOpen = false;
}
Navigate(e);
}
private void NavigationService_Navigated(object sender, NavigationEventArgs e)
{
var item = PrimaryItems?.FirstOrDefault(i => i.PageType == e?.SourcePageType);
if (item == null)
{
item = SecondaryItems?.FirstOrDefault(i => i.PageType == e?.SourcePageType);
}
if (item != null)
{
ChangeSelected(_lastSelectedItem, item);
_lastSelectedItem = item;
}
}
private void ChangeSelected(object oldValue, object newValue)
{
if (oldValue != null)
{
(oldValue as ShellNavigationItem).IsSelected = false;
}
if (newValue != null)
{
(newValue as ShellNavigationItem).IsSelected = true;
}
}
private void Navigate(object item)
{
var navigationItem = item as ShellNavigationItem;
if (navigationItem != null)
{
NavigationService.Navigate(navigationItem.PageType);
}
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
<Page
x:Class="RidoShop.Client.Views.InsightsPage"
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="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition x:Name="TitleRow" Height="48"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock
x:Name="TitlePage"
x:Uid="Insights_Pivot"
Text="Navigation Item 1"
FontSize="28" FontWeight="SemiLight" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" VerticalAlignment="Center"
Margin="12,0,12,7"/>
<Pivot Grid.Row="1">
<PivotItem x:Uid="Insights_PivotItem1">
<Grid Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</PivotItem>
<PivotItem x:Uid="Insights_PivotItem2">
<Grid Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--
The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.
-->
</Grid>
</PivotItem>
</Pivot>
<!-- Adaptive triggers -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TitlePage.Margin" Value="48,0,12,7"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,15 @@
using RidoShop.Client.ViewModels;
using Windows.UI.Xaml.Controls;
namespace RidoShop.Client.Views
{
public sealed partial class InsightsPage : Page
{
public InsightsViewModel ViewModel { get; } = new InsightsViewModel();
public InsightsPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
<Page
x:Class="RidoShop.Client.Views.MainPage"
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
x:Name="ContentArea"
Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition x:Name="TitleRow" Height="48"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock
x:Name="TitlePage"
x:Uid="Main_Title"
FontSize="28" FontWeight="SemiLight" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" VerticalAlignment="Center"
Margin="0,0,12,7"/>
<Grid
Grid.Row="1"
Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
<!--The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
Place your content here.-->
</Grid>
<!-- Adaptive triggers -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TitlePage.Margin" Value="48,0,12,7"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,15 @@
using RidoShop.Client.ViewModels;
using Windows.UI.Xaml.Controls;
namespace RidoShop.Client.Views
{
public sealed partial class MainPage : Page
{
public MainViewModel ViewModel { get; } = new MainViewModel();
public MainPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,77 @@
<Page
x:Class="RidoShop.Client.Views.SettingsPage"
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"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:i="using:Microsoft.Xaml.Interactivity"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Margin="12,0">
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
x:Uid="Settings_Title"
x:Name="TitlePage"
FontSize="28" FontWeight="SemiLight" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" VerticalAlignment="Center"
Margin="0,0,12,7"/>
<StackPanel Grid.Row="1" Margin="0,16,0,0">
<TextBlock
x:Uid="Settings_Theme"
Style="{ThemeResource TitleTextBlockStyle}"/>
<ToggleSwitch
x:Uid="Settings_Toggle"
IsOn="{x:Bind ViewModel.IsLightThemeEnabled, Mode=OneWay}"
Margin="0,4,0,0">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="Toggled">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.SwitchThemeCommand}"/>
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</ToggleSwitch>
</StackPanel>
<StackPanel Grid.Row="2" Margin="0,16,0,0">
<TextBlock
x:Uid="Settings_About"
Style="{ThemeResource TitleTextBlockStyle}"/>
<TextBlock
Text="{x:Bind ViewModel.AppDescription, Mode=OneWay}"
Style="{ThemeResource SubtitleTextBlockStyle}"
Margin="0,4,0,0"/>
<TextBlock
x:Uid="Settings_AboutDescription"
Style="{ThemeResource BodyTextBlockStyle}"/>
<HyperlinkButton
x:Uid="Settings_PrivacyTermsLink"
Margin="0,8,0,0"/>
</StackPanel>
</Grid>
<!-- Adaptive triggers -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="TitlePage.Margin" Value="48,0,12,7"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,23 @@
using RidoShop.Client.ViewModels;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace RidoShop.Client.Views
{
public sealed partial class SettingsPage : Page
{
public SettingsViewModel ViewModel { get; } = new SettingsViewModel();
// TODO UWPTemplates: Setup your privacy web in your Resource File, currently set to https://YourPrivacyUrlGoesHere
public SettingsPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.Initialize();
}
}
}

Просмотреть файл

@ -0,0 +1,125 @@
<Page
x:Class="RidoShop.Client.Views.ShellPage"
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"
xmlns:vm="using:RidoShop.Client.ViewModels"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:i="using:Microsoft.Xaml.Interactivity"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="NavigationMenuItemDataTemplate" x:DataType="vm:ShellNavigationItem">
<Button
Margin="0"
Padding="0,9"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Background="Transparent"
BorderThickness="0"
AutomationProperties.AccessibilityView="Control"
AutomationProperties.LandmarkType="Navigation"
AutomationProperties.Name="{x:Bind Label}"
Command="{Binding ElementName=ShellContent, Path=DataContext.ItemSelectedCommand}"
CommandParameter="{Binding}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle
Width="6"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Fill="{ThemeResource SystemControlForegroundAccentBrush}"
Visibility="{x:Bind SelectedVis, Mode=OneWay}" />
<FontIcon
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
Foreground="{x:Bind SelectedForeground, Mode=OneWay}"
Glyph="{x:Bind SymbolAsChar}" />
<TextBlock
Grid.Column="1"
Margin="0,0,24,0"
VerticalAlignment="Center"
Foreground="{x:Bind SelectedForeground, Mode=OneWay}"
Text="{x:Bind Label}"
TextTrimming="CharacterEllipsis" />
</Grid>
</Button>
</DataTemplate>
</Page.Resources>
<Grid x:Name="ShellContent" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- Top-level navigation menu + app content -->
<SplitView
x:Name="NavigationMenu"
Grid.RowSpan="2"
DisplayMode="{x:Bind ViewModel.DisplayMode, Mode=OneWay}"
PaneBackground="{ThemeResource SystemControlBackgroundAltHighBrush}"
IsPaneOpen="{x:Bind ViewModel.IsPaneOpen, Mode=TwoWay}">
<SplitView.Pane>
<Grid Margin="0,48,0,0">
<ScrollViewer VerticalAlignment="Stretch" TabNavigation="Local">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl
VerticalAlignment="Top"
IsTabStop="False"
ItemTemplate="{StaticResource NavigationMenuItemDataTemplate}"
ItemsSource="{x:Bind ViewModel.PrimaryItems}" />
<ItemsControl
Grid.Row="1"
VerticalAlignment="Bottom"
IsTabStop="False"
ItemTemplate="{StaticResource NavigationMenuItemDataTemplate}"
ItemsSource="{x:Bind ViewModel.SecondaryItems}" />
</Grid>
</ScrollViewer>
</Grid>
</SplitView.Pane>
<Grid Background="{ThemeResource SystemControlBackgroundAltHighBrush}">
<Frame x:Name="shellFrame"/>
</Grid>
</SplitView>
<!-- Mavigation menu button -->
<Button Width="48" Height="48" BorderThickness="0" Background="Transparent" Command="{x:Bind ViewModel.OpenPaneCommand}">
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE700;" FontSize="16"/>
</Button>
<!-- Adaptive triggers -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="CurrentStateChanged">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.StateChangedCommand}"/>
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<VisualState x:Name="PanoramicState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1024"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640"/>
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,18 @@
using RidoShop.Client.ViewModels;
using Windows.UI.Xaml.Controls;
namespace RidoShop.Client.Views
{
public sealed partial class ShellPage : Page
{
public ShellViewModel ViewModel { get; } = new ShellViewModel();
public ShellPage()
{
InitializeComponent();
DataContext = ViewModel;
ViewModel.Initialize(shellFrame);
}
}
}

Просмотреть файл

@ -200,7 +200,7 @@ namespace RidoShop.Sensors
HttpResponseMessage message = await http
.PostAsync(new Uri(baseuri + "/api/event"),
new HttpStringContent(newEvent.ToJson(),
UnicodeEncoding.Utf8, "application/json"));
Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json"));
}