Splitted and added UWP project
@@ -0,0 +1,7 @@
|
|||||||
|
<Application
|
||||||
|
x:Class="GUTSchedule.UWP.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:GUTSchedule.UWP">
|
||||||
|
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.ApplicationModel;
|
||||||
|
using Windows.ApplicationModel.Activation;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
namespace GUTSchedule.UWP
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
sealed partial class App : Application
|
||||||
|
{
|
||||||
|
/// <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();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,174 @@
|
|||||||
|
<?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>{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}</ProjectGuid>
|
||||||
|
<OutputType>AppContainerExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>GUTSchedule.UWP</RootNamespace>
|
||||||
|
<AssemblyName>GUTSchedule.UWP</AssemblyName>
|
||||||
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||||
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.16299.0</TargetPlatformVersion>
|
||||||
|
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||||
|
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
|
||||||
|
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
|
||||||
|
</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|ARM64'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\ARM64\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>ARM64</PlatformTarget>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM64'">
|
||||||
|
<OutputPath>bin\ARM64\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<NoWarn>;2008</NoWarn>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>ARM64</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>
|
||||||
|
<Compile Include="App.xaml.cs">
|
||||||
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="MainPage.xaml.cs">
|
||||||
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AppxManifest>
|
||||||
|
</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>
|
||||||
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</ApplicationDefinition>
|
||||||
|
<Page Include="MainPage.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||||
|
<Version>6.2.9</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GUTSchedule\GUTSchedule.csproj">
|
||||||
|
<Project>{a6f6de35-0eb4-4d11-9ff9-f4601595b639}</Project>
|
||||||
|
<Name>GUTSchedule</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '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,14 @@
|
|||||||
|
<Page
|
||||||
|
x:Class="GUTSchedule.UWP.MainPage"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:GUTSchedule.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>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
|
||||||
|
|
||||||
|
namespace GUTSchedule.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()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?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"
|
||||||
|
IgnorableNamespaces="uap mp">
|
||||||
|
|
||||||
|
<Identity
|
||||||
|
Name="3f032359-f68f-4a46-b88c-113efc87b82b"
|
||||||
|
Publisher="CN=Michael Gordeev"
|
||||||
|
Version="1.0.0.0" />
|
||||||
|
|
||||||
|
<mp:PhoneIdentity PhoneProductId="3f032359-f68f-4a46-b88c-113efc87b82b" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>GUT.Schedule.UWP</DisplayName>
|
||||||
|
<PublisherDisplayName>Michael Gordeev</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="GUT.Schedule.UWP.App">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="GUT.Schedule.UWP"
|
||||||
|
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||||
|
Square44x44Logo="Assets\Square44x44Logo.png"
|
||||||
|
Description="GUT.Schedule.UWP"
|
||||||
|
BackgroundColor="transparent">
|
||||||
|
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
|
||||||
|
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<Capability Name="internetClient" />
|
||||||
|
</Capabilities>
|
||||||
|
</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("GUT.Schedule.UWP")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("GUT.Schedule.UWP")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||||
|
[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" Serialize="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>
|
||||||
@@ -3,24 +3,147 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.29609.76
|
VisualStudioVersion = 16.0.29609.76
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUT.Schedule", "GUT.Schedule\GUT.Schedule.csproj", "{A0471165-37F5-4309-8A92-42F1A6589EEE}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUTSchedule.Droid", "GUTSchedule.Droid\GUTSchedule.Droid.csproj", "{A0471165-37F5-4309-8A92-42F1A6589EEE}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUTSchedule.UWP", "GUT.Schedule.UWP\GUTSchedule.UWP.csproj", "{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GUTSchedule", "GUTSchedule\GUTSchedule.csproj", "{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|ARM = Debug|ARM
|
||||||
|
Debug|ARM64 = Debug|ARM64
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release (APK)|Any CPU = Release (APK)|Any CPU
|
Release (APK)|Any CPU = Release (APK)|Any CPU
|
||||||
|
Release (APK)|ARM = Release (APK)|ARM
|
||||||
|
Release (APK)|ARM64 = Release (APK)|ARM64
|
||||||
|
Release (APK)|x64 = Release (APK)|x64
|
||||||
|
Release (APK)|x86 = Release (APK)|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|ARM = Release|ARM
|
||||||
|
Release|ARM64 = Release|ARM64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM.Deploy.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|ARM64.Deploy.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.ActiveCfg = Release (APK)|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.ActiveCfg = Release (APK)|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.Build.0 = Release (APK)|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.Build.0 = Release (APK)|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.Deploy.0 = Release (APK)|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|Any CPU.Deploy.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM.ActiveCfg = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM.Build.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM.Deploy.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM64.ActiveCfg = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM64.Build.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|ARM64.Deploy.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x64.ActiveCfg = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x64.Build.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x64.Deploy.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x86.ActiveCfg = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x86.Build.0 = Release (APK)|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release (APK)|x86.Deploy.0 = Release (APK)|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM.Deploy.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM64.Build.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|ARM64.Deploy.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x64.Deploy.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A0471165-37F5-4309-8A92-42F1A6589EEE}.Release|x86.Deploy.0 = Release|Any CPU
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x64.Deploy.0 = Debug|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Debug|x86.Deploy.0 = Debug|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|Any CPU.Build.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|Any CPU.Deploy.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM.ActiveCfg = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM.Build.0 = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM.Deploy.0 = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM64.Build.0 = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|ARM64.Deploy.0 = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x64.ActiveCfg = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x64.Build.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x64.Deploy.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x86.ActiveCfg = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x86.Build.0 = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release (APK)|x86.Deploy.0 = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|Any CPU.ActiveCfg = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM.Deploy.0 = Release|ARM
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x64.Build.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x64.Deploy.0 = Release|x64
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x86.Build.0 = Release|x86
|
||||||
|
{AC7E8D95-1E2A-409C-9A95-477C2AC8E47F}.Release|x86.Deploy.0 = Release|x86
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|ARM.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|ARM64.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|ARM64.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|x64.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release (APK)|x86.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|ARM64.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A6F6DE35-0EB4-4D11-9FF9-F4601595B639}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Content.PM;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Support.V4.Text;
|
|
||||||
using Android.Support.V7.App;
|
|
||||||
using Android.Text.Method;
|
|
||||||
using Android.Widget;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Activities
|
|
||||||
{
|
|
||||||
[Activity(Label = "@string/aboutTitle")]
|
|
||||||
public class AboutActivity : AppCompatActivity
|
|
||||||
{
|
|
||||||
protected override async void OnCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
(string name, string handle, string link)[] contacts = new (string, string, string)[]
|
|
||||||
{
|
|
||||||
(Resources.GetText(Resource.String.websiteContact), "https://xfox111.net", "https://xfox111.net"),
|
|
||||||
(Resources.GetText(Resource.String.twitterContact), "@xfox111", "https://twitter.com/xfox111"),
|
|
||||||
(Resources.GetText(Resource.String.vkontakteContact), "@xfox.mike", "https://vk.com/xfox.mike"),
|
|
||||||
("LinkedIn", "@xfox", "https://linkedin.com/in/xfox"),
|
|
||||||
("GitHub", "@xfox111", "https://github.com/xfox111"),
|
|
||||||
};
|
|
||||||
(string name, string link)[] links = new (string, string)[]
|
|
||||||
{
|
|
||||||
(Resources.GetText(Resource.String.privacyPolicyLink), "https://xfox111.net/Projects/GUTSchedule/PrivacyPolicy.txt"),
|
|
||||||
("General Public License v3", "https://www.gnu.org/licenses/gpl-3.0"),
|
|
||||||
(Resources.GetText(Resource.String.repositoryLink), "https://github.com/xfox111/gutschedule"),
|
|
||||||
(Resources.GetText(Resource.String.notsLink), "http://tios.spbgut.ru/index.php"),
|
|
||||||
(Resources.GetText(Resource.String.sutLink), "https://sut.ru"),
|
|
||||||
};
|
|
||||||
|
|
||||||
base.OnCreate(savedInstanceState);
|
|
||||||
SetContentView(Resource.Layout.About);
|
|
||||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
|
||||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
|
||||||
|
|
||||||
FindViewById<Button>(Resource.Id.feedback).Click += (s, e) =>
|
|
||||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
|
||||||
|
|
||||||
FindViewById<TextView>(Resource.Id.contacts).SetText(
|
|
||||||
HtmlCompat.FromHtml(string.Join("<br />", contacts.Select(i => $"<span>{i.name}:</span> <a href=\"{i.link}\">{i.handle}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
|
||||||
TextView.BufferType.Normal);
|
|
||||||
FindViewById<TextView>(Resource.Id.contacts).MovementMethod = LinkMovementMethod.Instance;
|
|
||||||
|
|
||||||
FindViewById<TextView>(Resource.Id.links).SetText(
|
|
||||||
HtmlCompat.FromHtml(string.Join("<br />", links.Select(i => $"<a href=\"{i.link}\">{i.name}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
|
||||||
TextView.BufferType.Normal);
|
|
||||||
FindViewById<TextView>(Resource.Id.links).MovementMethod = LinkMovementMethod.Instance;
|
|
||||||
|
|
||||||
List<string> contributors = new List<string>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using HttpClient client = new HttpClient();
|
|
||||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/xfox111/gutschedule/contributors");
|
|
||||||
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
string resposeContent = await response.Content.ReadAsStringAsync();
|
|
||||||
dynamic parsedResponse = JsonConvert.DeserializeObject(resposeContent);
|
|
||||||
|
|
||||||
foreach (var i in parsedResponse)
|
|
||||||
if (i.type == "User" && ((string)i.login).ToLower() != "xfox111")
|
|
||||||
contributors.Add((string)i.login);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (contributors.Count > 0)
|
|
||||||
{
|
|
||||||
FindViewById<TextView>(Resource.Id.contributors).SetText(
|
|
||||||
HtmlCompat.FromHtml(string.Join(", ", contributors.Select(i => $"<a href=\"https://github.com/{i}\">@{i}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
|
||||||
TextView.BufferType.Normal);
|
|
||||||
FindViewById<TextView>(Resource.Id.contributors).MovementMethod = LinkMovementMethod.Instance;
|
|
||||||
|
|
||||||
FindViewById<TextView>(Resource.Id.contributorsTitle).Visibility = Android.Views.ViewStates.Visible;
|
|
||||||
FindViewById<TextView>(Resource.Id.contributors).Visibility = Android.Views.ViewStates.Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
using Android.App;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Widget;
|
|
||||||
using GUT.Schedule.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Activities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Shows status of schedule export process
|
|
||||||
/// </summary>
|
|
||||||
[Activity(Theme = "@style/AppTheme.Light.SplashScreen")]
|
|
||||||
public class ExportActivity : Activity
|
|
||||||
{
|
|
||||||
TextView status;
|
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
base.OnCreate(savedInstanceState);
|
|
||||||
SetContentView(Resource.Layout.Export);
|
|
||||||
|
|
||||||
status = FindViewById<TextView>(Resource.Id.status);
|
|
||||||
|
|
||||||
Export();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Export()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(Data.DataSet.IsProfessor == true)
|
|
||||||
status.Text = Resources.GetText(Resource.String.potatoLoadingStatus); // For some reason professors' schedule loads much slower
|
|
||||||
else
|
|
||||||
status.Text = Resources.GetText(Resource.String.loadingStatus);
|
|
||||||
|
|
||||||
if (Data.DataSet.HttpClient != null)
|
|
||||||
{
|
|
||||||
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
|
||||||
|
|
||||||
for(DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
|
||||||
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, false)); // Even though the user can be professor he can be also PhD student (and have his student schedule)
|
|
||||||
|
|
||||||
if(Data.DataSet.IsProfessor == true)
|
|
||||||
for (DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
|
||||||
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, true));
|
|
||||||
|
|
||||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
|
||||||
Calendar.Export(schedule);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
List<Subject> schedule = await Parser.LoadSchedule();
|
|
||||||
|
|
||||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
|
||||||
Calendar.Export(schedule);
|
|
||||||
}
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.doneStatus);
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException e)
|
|
||||||
{
|
|
||||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
|
||||||
builder.SetMessage(Resources.GetText(Resource.String.connectionFailMessage))
|
|
||||||
.SetTitle(e.Message)
|
|
||||||
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed())
|
|
||||||
.SetNegativeButton(Resources.GetText(Resource.String.repeat), (s, e) => Export());
|
|
||||||
|
|
||||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
|
||||||
dialog.Show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
|
||||||
builder.SetMessage(e.Message)
|
|
||||||
.SetTitle(e.GetType().ToString())
|
|
||||||
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed());
|
|
||||||
|
|
||||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
|
||||||
dialog.Show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
base.OnBackPressed(); // Navigates back to main activity (always because I don't allow backward navigation)
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnBackPressed() { } // Disables back button
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,353 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Content.PM;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Preferences;
|
|
||||||
using Android.Support.V4.Text;
|
|
||||||
using Android.Support.V7.App;
|
|
||||||
using Android.Text.Method;
|
|
||||||
using Android.Views;
|
|
||||||
using Android.Widget;
|
|
||||||
using AngleSharp.Html.Dom;
|
|
||||||
using AngleSharp.Html.Parser;
|
|
||||||
using GUT.Schedule.Models;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Activities
|
|
||||||
{
|
|
||||||
[Activity]
|
|
||||||
public class MainActivity : AppCompatActivity
|
|
||||||
{
|
|
||||||
Button start, end, export;
|
|
||||||
Button forDay, forWeek, forMonth, forSemester;
|
|
||||||
Spinner faculty, course, group, reminder, calendar;
|
|
||||||
CheckBox groupTitle, authorize;
|
|
||||||
TextView error;
|
|
||||||
LinearLayout studentParams, profParams;
|
|
||||||
EditText email, password;
|
|
||||||
|
|
||||||
ISharedPreferences prefs;
|
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
base.OnCreate(savedInstanceState);
|
|
||||||
SetContentView(Resource.Layout.Main);
|
|
||||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
|
||||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
|
||||||
|
|
||||||
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
|
||||||
|
|
||||||
AssignVariables();
|
|
||||||
|
|
||||||
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
|
||||||
int s = Data.Faculties.FindIndex(i => i.Id == prefs.GetString("Faculty", "-123"));
|
|
||||||
faculty.SetSelection(s == -1 ? 0 : s);
|
|
||||||
|
|
||||||
course.SetList(this, "1234".ToCharArray());
|
|
||||||
course.SetSelection(prefs.GetInt("Course", 0)); // IDK why but this shit triggers events anyway (even if they are set in the next line. It seem to be that there's some asynchronous shit somewhere there)
|
|
||||||
// P.S. Fuck Android
|
|
||||||
|
|
||||||
AddEvents();
|
|
||||||
|
|
||||||
// Settings spinners' dropdown lists content
|
|
||||||
reminder.SetList(this, new[]
|
|
||||||
{
|
|
||||||
Resources.GetText(Resource.String.noReminderOption),
|
|
||||||
Resources.GetText(Resource.String.inTimeReminderOption),
|
|
||||||
Resources.GetText(Resource.String.fiveMinuteReminderOption),
|
|
||||||
Resources.GetText(Resource.String.tenMinuteReminderOption)
|
|
||||||
});
|
|
||||||
reminder.SetSelection(prefs.GetInt("Reminder", 0));
|
|
||||||
|
|
||||||
calendar.SetList(this, Calendar.Calendars.Select(i => i.Name));
|
|
||||||
s = Calendar.Calendars.FindIndex(i => i.Id == prefs.GetString("Calendar", "-123"));
|
|
||||||
calendar.SetSelection(s == -1 ? 0 : s);
|
|
||||||
|
|
||||||
end.Text = Data.EndDate.ToShortDateString();
|
|
||||||
start.Text = Data.StartDate.ToShortDateString();
|
|
||||||
|
|
||||||
groupTitle.Checked = prefs.GetBoolean("AddGroupToHeader", false);
|
|
||||||
authorize.Checked = prefs.GetBoolean("Authorize", true);
|
|
||||||
|
|
||||||
email.Text = prefs.GetString("email", "");
|
|
||||||
password.Text = prefs.GetString("password", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Export_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
error.Visibility = ViewStates.Gone;
|
|
||||||
|
|
||||||
if (Data.StartDate > Data.EndDate)
|
|
||||||
{
|
|
||||||
error.Text = Resources.GetText(Resource.String.invalidDateRangeError);
|
|
||||||
error.Visibility = ViewStates.Visible;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpClient client = null;
|
|
||||||
bool? isProf = null;
|
|
||||||
if(authorize.Checked)
|
|
||||||
{
|
|
||||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.authorizationState), ToastLength.Short).Show();
|
|
||||||
if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text))
|
|
||||||
{
|
|
||||||
error.Text = Resources.GetText(Resource.String.invalidAuthorizationError);
|
|
||||||
error.Visibility = ViewStates.Visible;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
export.Enabled = false;
|
|
||||||
client = new HttpClient();
|
|
||||||
|
|
||||||
await client.GetAsync("https://cabs.itut.ru/cabinet/");
|
|
||||||
|
|
||||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php");
|
|
||||||
request.SetContent(
|
|
||||||
("users", email.Text),
|
|
||||||
("parole", password.Text));
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
string responseContent = await response.GetString();
|
|
||||||
export.Enabled = true;
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
error.Text = $"{Resources.GetText(Resource.String.authorizationError)}: {response.StatusCode}: {responseContent}";
|
|
||||||
error.Visibility = ViewStates.Visible;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
error.Text = $"{Resources.GetText(Resource.String.invalidCredentialError)} ({string.Join("; ", responseContent.Replace("error=", "", StringComparison.OrdinalIgnoreCase).Split('|'))})";
|
|
||||||
error.Visibility = ViewStates.Visible;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
export.Enabled = false;
|
|
||||||
HttpResponseMessage verificationResponse = await client.GetAsync("https://cabs.itut.ru/cabinet/?login=yes");
|
|
||||||
export.Enabled = true;
|
|
||||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await verificationResponse.GetString());
|
|
||||||
if (doc.QuerySelectorAll("option").Any(i => i.TextContent.Contains("Сотрудник")))
|
|
||||||
isProf = true;
|
|
||||||
else
|
|
||||||
isProf = false;
|
|
||||||
|
|
||||||
Data.Groups = null;
|
|
||||||
|
|
||||||
// Если ты это читаешь и у тебя возникли вопросы по типу "А какого хуя творится в коде ниже?!", то во-первых:
|
|
||||||
// According to this SO thread: https://stackoverflow.com/questions/1925486/android-storing-username-and-password
|
|
||||||
// I consider Preferences as safe enough method for storing credentials
|
|
||||||
// А во-вторых, даже такой казалось бы небезопасный метод хранения учетных данных в сто раз надежнее того дерьма,
|
|
||||||
// что творится на серверах Бонча (я не шучу, там все ОЧЕНЬ плохо)
|
|
||||||
// Ну и в-третьих: Андроид - это пиздец и настоящий ад разработчика. И если бы была моя воля, я бы под него никогда не писал #FuckAndroid
|
|
||||||
// З.Ы. Помнишь про второй пункт? Так вот, если ты используешь такой же пароль как в ЛК где-то еще, настоятельно рекомендую его поменять
|
|
||||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("email", email.Text).Apply();
|
|
||||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("password", password.Text).Apply();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(Data.Groups.Count < 1)
|
|
||||||
{
|
|
||||||
error.Text = Resources.GetText(Resource.String.groupSelectionError);
|
|
||||||
error.Visibility = ViewStates.Visible;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forming export parameters
|
|
||||||
Data.DataSet = new DataSet
|
|
||||||
{
|
|
||||||
Faculty = Data.Faculties[faculty.SelectedItemPosition].Id,
|
|
||||||
Group = Data.Groups?[group.SelectedItemPosition].Id,
|
|
||||||
Course = course.SelectedItemPosition + 1,
|
|
||||||
AddGroupToTitle = groupTitle.Checked,
|
|
||||||
Calendar = Calendar.Calendars[calendar.SelectedItemPosition].Id,
|
|
||||||
Reminder = (reminder.SelectedItemPosition - 1) * 5,
|
|
||||||
HttpClient = client,
|
|
||||||
IsProfessor = isProf
|
|
||||||
};
|
|
||||||
|
|
||||||
StartActivity(new Intent(this, typeof(ExportActivity)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void End_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Data.EndDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.EndDate);
|
|
||||||
end.Text = Data.EndDate.ToShortDateString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Start_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Data.StartDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.StartDate);
|
|
||||||
start.Text = Data.StartDate.ToShortDateString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void UpdateGroupsList()
|
|
||||||
{
|
|
||||||
if (course.SelectedItem == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1);
|
|
||||||
group.SetList(this, Data.Groups.Select(i => i.Name));
|
|
||||||
|
|
||||||
int s = Data.Groups?.FindIndex(i => i.Id == prefs.GetString("Group", "-123")) ?? 0;
|
|
||||||
group.SetSelection(s == -1 ? 0 : s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetDate(int days)
|
|
||||||
{
|
|
||||||
Data.EndDate = Data.StartDate.AddDays(days);
|
|
||||||
end.Text = Data.EndDate.ToShortDateString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Init stuff
|
|
||||||
private void AssignVariables()
|
|
||||||
{
|
|
||||||
start = FindViewById<Button>(Resource.Id.start);
|
|
||||||
end = FindViewById<Button>(Resource.Id.end);
|
|
||||||
export = FindViewById<Button>(Resource.Id.export);
|
|
||||||
|
|
||||||
forDay = FindViewById<Button>(Resource.Id.forDay);
|
|
||||||
forWeek = FindViewById<Button>(Resource.Id.forWeek);
|
|
||||||
forMonth = FindViewById<Button>(Resource.Id.forMonth);
|
|
||||||
forSemester = FindViewById<Button>(Resource.Id.forSemester);
|
|
||||||
|
|
||||||
faculty = FindViewById<Spinner>(Resource.Id.faculty);
|
|
||||||
course = FindViewById<Spinner>(Resource.Id.course);
|
|
||||||
group = FindViewById<Spinner>(Resource.Id.group);
|
|
||||||
reminder = FindViewById<Spinner>(Resource.Id.reminder);
|
|
||||||
calendar = FindViewById<Spinner>(Resource.Id.calendar);
|
|
||||||
|
|
||||||
error = FindViewById<TextView>(Resource.Id.error);
|
|
||||||
|
|
||||||
groupTitle = FindViewById<CheckBox>(Resource.Id.groupTitle);
|
|
||||||
authorize = FindViewById<CheckBox>(Resource.Id.authorization);
|
|
||||||
|
|
||||||
studentParams = FindViewById<LinearLayout>(Resource.Id.studentParams);
|
|
||||||
profParams = FindViewById<LinearLayout>(Resource.Id.professorParams);
|
|
||||||
|
|
||||||
email = FindViewById<EditText>(Resource.Id.email);
|
|
||||||
password = FindViewById<EditText>(Resource.Id.password);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddEvents()
|
|
||||||
{
|
|
||||||
faculty.ItemSelected += (s, e) =>
|
|
||||||
{
|
|
||||||
prefs.Edit().PutString("Faculty", Data.Faculties[e.Position].Id).Apply();
|
|
||||||
UpdateGroupsList();
|
|
||||||
};
|
|
||||||
course.ItemSelected += (s, e) =>
|
|
||||||
{
|
|
||||||
prefs.Edit().PutInt("Course", e.Position).Apply();
|
|
||||||
UpdateGroupsList();
|
|
||||||
};
|
|
||||||
authorize.CheckedChange += (s, e) =>
|
|
||||||
{
|
|
||||||
prefs.Edit().PutBoolean("Authorize", e.IsChecked).Apply();
|
|
||||||
if (e.IsChecked)
|
|
||||||
{
|
|
||||||
studentParams.Visibility = ViewStates.Gone;
|
|
||||||
profParams.Visibility = ViewStates.Visible;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
studentParams.Visibility = ViewStates.Visible;
|
|
||||||
profParams.Visibility = ViewStates.Gone;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
calendar.ItemSelected += (s, e) =>
|
|
||||||
prefs.Edit().PutString("Calendar", Calendar.Calendars[e.Position].Id).Apply();
|
|
||||||
reminder.ItemSelected += (s, e) =>
|
|
||||||
prefs.Edit().PutInt("Reminder", e.Position).Apply();
|
|
||||||
group.ItemSelected += (s, e) =>
|
|
||||||
prefs.Edit().PutString("Group", Data.Groups[e.Position].Id).Apply();
|
|
||||||
|
|
||||||
groupTitle.Click += (s, e) =>
|
|
||||||
prefs.Edit().PutBoolean("AddGroupToHeader", groupTitle.Checked).Apply();
|
|
||||||
|
|
||||||
|
|
||||||
forDay.Click += (s, e) => SetDate(0);
|
|
||||||
forWeek.Click += (s, e) => SetDate(6);
|
|
||||||
forMonth.Click += (s, e) => SetDate(30);
|
|
||||||
forSemester.Click += (s, e) =>
|
|
||||||
{
|
|
||||||
Data.EndDate = DateTime.Today.Month > 8 ? new DateTime(DateTime.Today.Year + 1, 1, 1) : new DateTime(DateTime.Today.Year, 8, 31);
|
|
||||||
end.Text = Data.EndDate.ToShortDateString();
|
|
||||||
};
|
|
||||||
|
|
||||||
start.Click += Start_Click;
|
|
||||||
end.Click += End_Click;
|
|
||||||
|
|
||||||
export.Click += Export_Click;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Menu stuff
|
|
||||||
public override bool OnCreateOptionsMenu(IMenu menu)
|
|
||||||
{
|
|
||||||
MenuInflater.Inflate(Resource.Menu.MainContextMenu, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear(bool keepPrevious = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.clearingStatus), ToastLength.Short).Show();
|
|
||||||
Calendar.Clear(keepPrevious);
|
|
||||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.doneStatus), ToastLength.Short).Show();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
|
||||||
builder.SetMessage(e.Message)
|
|
||||||
.SetTitle(e.GetType().ToString())
|
|
||||||
.SetPositiveButton("ОК", (IDialogInterfaceOnClickListener)null);
|
|
||||||
|
|
||||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
|
||||||
dialog.Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool OnOptionsItemSelected(IMenuItem item)
|
|
||||||
{
|
|
||||||
Android.Support.V7.App.AlertDialog.Builder builder;
|
|
||||||
Android.Support.V7.App.AlertDialog dialog;
|
|
||||||
switch (item.ItemId)
|
|
||||||
{
|
|
||||||
case Resource.Id.about:
|
|
||||||
StartActivity(new Intent(this, typeof(AboutActivity)));
|
|
||||||
return true;
|
|
||||||
case Resource.Id.email:
|
|
||||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case Resource.Id.clear:
|
|
||||||
builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
|
||||||
builder.SetMessage(Resources.GetText(Resource.String.clearScheduleMessage))
|
|
||||||
.SetTitle(Resources.GetText(Resource.String.clearScheduleTitle))
|
|
||||||
.SetPositiveButton(Resources.GetText(Resource.String.clearUpcomingOption), (s, e) => Clear())
|
|
||||||
.SetNegativeButton(Resources.GetText(Resource.String.clearAllOption), (s, e) => Clear(false))
|
|
||||||
.SetNeutralButton(Resources.GetText(Resource.String.cancelOption), (IDialogInterfaceOnClickListener)null);
|
|
||||||
|
|
||||||
dialog = builder.Create();
|
|
||||||
dialog.Show();
|
|
||||||
|
|
||||||
// Making links clickable
|
|
||||||
dialog.FindViewById<TextView>(Android.Resource.Id.Message).MovementMethod = LinkMovementMethod.Instance;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public override void OnBackPressed() =>
|
|
||||||
FinishAffinity(); // Close application
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
using Android;
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Content.PM;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Runtime;
|
|
||||||
using Android.Support.V4.App;
|
|
||||||
using Android.Support.V4.Content;
|
|
||||||
using Android.Support.V7.App;
|
|
||||||
using Android.Widget;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Activities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Splash screen activity. Loads init data
|
|
||||||
/// </summary>
|
|
||||||
[Activity(MainLauncher = true, Theme = "@style/AppTheme.Light.SplashScreen")]
|
|
||||||
public class StartActivity : AppCompatActivity
|
|
||||||
{
|
|
||||||
TextView status;
|
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
SetContentView(Resource.Layout.SplashScreen);
|
|
||||||
base.OnCreate(savedInstanceState);
|
|
||||||
|
|
||||||
status = FindViewById<TextView>(Resource.Id.status);
|
|
||||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
|
||||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.permissionsCheckStatus);
|
|
||||||
|
|
||||||
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteCalendar) != Permission.Granted)
|
|
||||||
{
|
|
||||||
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.WriteCalendar))
|
|
||||||
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
|
||||||
else
|
|
||||||
RequestPermissions();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Proceed()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
status.Text = Resources.GetText(Resource.String.calendarLoadingStatus);
|
|
||||||
Calendar.LoadCalendars();
|
|
||||||
if (Calendar.Calendars.Count == 0)
|
|
||||||
{
|
|
||||||
ShowDialog(Resources.GetText(Resource.String.createCalendarTitle), Resources.GetText(Resource.String.createCalendarMessage));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.facultiesLoadingStatus);
|
|
||||||
await Parser.LoadFaculties();
|
|
||||||
|
|
||||||
status.Text = Resources.GetText(Resource.String.offsetDatesLoadingStatus);
|
|
||||||
using HttpClient client = new HttpClient();
|
|
||||||
Data.FirstWeekDay = int.Parse(await client.GetStringAsync("https://xfox111.net/schedule_offset.txt"));
|
|
||||||
}
|
|
||||||
catch(HttpRequestException e)
|
|
||||||
{
|
|
||||||
ShowDialog(e.Message, Resources.GetText(Resource.String.connectionFailMessage), Proceed, FinishAndRemoveTask, Resources.GetText(Resource.String.repeat), Resources.GetText(Resource.String.quit));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ShowDialog(e.GetType().ToString(), e.Message, FinishAndRemoveTask);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
StartActivity(new Intent(this, typeof(MainActivity)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
|
|
||||||
{
|
|
||||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
|
|
||||||
if (grantResults.All(i => i == Permission.Granted))
|
|
||||||
Proceed();
|
|
||||||
else
|
|
||||||
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RequestPermissions() =>
|
|
||||||
ActivityCompat.RequestPermissions(this, new[]
|
|
||||||
{
|
|
||||||
Manifest.Permission.ReadCalendar,
|
|
||||||
Manifest.Permission.WriteCalendar,
|
|
||||||
Manifest.Permission.Internet
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
private void ShowDialog(string title, string content, Action posAction = null, Action negAction = null, string posActionLabel = null, string negActionLabel = null)
|
|
||||||
{
|
|
||||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
|
||||||
builder.SetMessage(content)
|
|
||||||
.SetTitle(title).SetPositiveButton(posActionLabel ?? "OK", (s, e) => posAction?.Invoke());
|
|
||||||
|
|
||||||
if (negAction != null)
|
|
||||||
builder.SetNegativeButton(negActionLabel ?? Resources.GetText(Resource.String.close), (s, e) => negAction.Invoke());
|
|
||||||
|
|
||||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
|
||||||
dialog.Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnBackPressed() { } // Disables back button
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Database;
|
|
||||||
using Android.Net;
|
|
||||||
using Android.Provider;
|
|
||||||
using GUT.Schedule.Models;
|
|
||||||
using Java.Util;
|
|
||||||
|
|
||||||
namespace GUT.Schedule
|
|
||||||
{
|
|
||||||
public static class Calendar
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// List of all existing Google calendars on the device
|
|
||||||
/// </summary>
|
|
||||||
public static List<(string Id, string Name)> Calendars { get; private set; } = new List<(string Id, string Name)>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves all Google Accounts' calendars existing on the device and puts them to <see cref="Calendars"/>
|
|
||||||
/// </summary>
|
|
||||||
public static void LoadCalendars()
|
|
||||||
{
|
|
||||||
Calendars = new List<(string, string)>(); // Resetting current calendars list
|
|
||||||
|
|
||||||
// Building calendar data retrieval projections
|
|
||||||
Uri calendarsUri = CalendarContract.Calendars.ContentUri;
|
|
||||||
string[] calendarsProjection = {
|
|
||||||
CalendarContract.Calendars.InterfaceConsts.Id,
|
|
||||||
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
|
|
||||||
CalendarContract.Calendars.InterfaceConsts.AccountName
|
|
||||||
};
|
|
||||||
|
|
||||||
// Retrieving calendars data
|
|
||||||
ICursor cursor = Application.Context.ContentResolver.Query(calendarsUri, calendarsProjection, null, null, null);
|
|
||||||
|
|
||||||
while (cursor.MoveToNext())
|
|
||||||
Calendars.Add((cursor.GetString(0), $"{cursor.GetString(1)} ({cursor.GetString(2)})"));
|
|
||||||
|
|
||||||
cursor.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Export(IEnumerable<Subject> schedule)
|
|
||||||
{
|
|
||||||
DataSet data = Data.DataSet;
|
|
||||||
|
|
||||||
foreach (Subject item in schedule)
|
|
||||||
{
|
|
||||||
ContentValues eventValues = new ContentValues();
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}.{1} {2} ({3})",
|
|
||||||
item.Order,
|
|
||||||
data.AddGroupToTitle ? $" [{item.Group}]" : "",
|
|
||||||
item.Name,
|
|
||||||
item.Type));
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Professor);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, string.Join(';', item.Cabinets));
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
|
||||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
|
||||||
|
|
||||||
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
|
||||||
|
|
||||||
// Settings reminder
|
|
||||||
if(data.Reminder != -5)
|
|
||||||
{
|
|
||||||
ContentValues reminderValues = new ContentValues();
|
|
||||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
|
||||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
|
||||||
|
|
||||||
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Export(IEnumerable<CabinetSubject> schedule)
|
|
||||||
{
|
|
||||||
DataSet data = Data.DataSet;
|
|
||||||
|
|
||||||
foreach (CabinetSubject item in schedule)
|
|
||||||
{
|
|
||||||
ContentValues eventValues = new ContentValues();
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}{1}. {2} ({3})",
|
|
||||||
item.ProfessorSchedule ? "📚 " : (data.AddGroupToTitle ? $"[{data.Group}] " : ""),
|
|
||||||
item.Order,
|
|
||||||
item.Name,
|
|
||||||
item.Type));
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Opponent);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, item.Cabinet);
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
|
||||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
|
||||||
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
|
||||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
|
||||||
|
|
||||||
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
|
||||||
|
|
||||||
// Settings reminder
|
|
||||||
if(data.Reminder != -5)
|
|
||||||
{
|
|
||||||
ContentValues reminderValues = new ContentValues();
|
|
||||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
|
||||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
|
||||||
|
|
||||||
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Clear(bool keepPrevious = true)
|
|
||||||
{
|
|
||||||
Uri contentUri = CalendarContract.Events.ContentUri;
|
|
||||||
string selector = $"({CalendarContract.Events.InterfaceConsts.CustomAppPackage} == \"{Application.Context.PackageName}\") AND (deleted != 1)";
|
|
||||||
if (keepPrevious)
|
|
||||||
selector += $" AND (dtstart > {System.DateTime.Now.ToUnixTime()})";
|
|
||||||
|
|
||||||
string[] calendarsProjection = {
|
|
||||||
CalendarContract.Events.InterfaceConsts.Id,
|
|
||||||
CalendarContract.Events.InterfaceConsts.Dtstart,
|
|
||||||
CalendarContract.Events.InterfaceConsts.CustomAppPackage,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Retrieving calendars data
|
|
||||||
ICursor cursor = Application.Context.ContentResolver.Query(contentUri, calendarsProjection, selector, null, null);
|
|
||||||
while (cursor.MoveToNext())
|
|
||||||
Application.Context.ContentResolver.Delete(ContentUris.WithAppendedId(CalendarContract.Events.ContentUri, cursor.GetLong(0)), null, null);
|
|
||||||
|
|
||||||
cursor.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Widget;
|
|
||||||
|
|
||||||
namespace GUT.Schedule
|
|
||||||
{
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Sets array as Spinner dropdown list content
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">Array items type</typeparam>
|
|
||||||
/// <param name="spinner">Spinner on which array will be assigned to</param>
|
|
||||||
/// <param name="context">Current activity context. In most common cases <c>this</c> will do</param>
|
|
||||||
/// <param name="array">Array of items to be displayed</param>
|
|
||||||
public static void SetList<T>(this Spinner spinner, Context context, IEnumerable<T> array)
|
|
||||||
{
|
|
||||||
ArrayAdapter adapter = new ArrayAdapter(context, Resource.Layout.support_simple_spinner_dropdown_item, array.ToList());
|
|
||||||
spinner.Adapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns <see cref="DateTime"/> instance based on study week number, weekday and semester start day number
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="week">Number of the study week</param>
|
|
||||||
/// <param name="weekday">Weekday</param>
|
|
||||||
/// <returns><see cref="DateTime"/> instance based on study week number, weekday and semester start day number</returns>
|
|
||||||
public static DateTime GetDateFromWeeks(int week, int weekday)
|
|
||||||
{
|
|
||||||
DateTime dt = new DateTime(DateTime.Today.Year, DateTime.Today.Month >= 8 ? 9 : 2, Data.FirstWeekDay);
|
|
||||||
|
|
||||||
dt = dt.AddDays(--week * 7);
|
|
||||||
dt = dt.AddDays(--weekday);
|
|
||||||
|
|
||||||
return dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts <see cref="DateTime"/> to milliseconds count
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>In the nearest future we will be fucked because of that shit</remarks>
|
|
||||||
/// <param name="dt"><see cref="DateTime"/> which is to be converted to UNIX time</param>
|
|
||||||
/// <returns><see cref="long"/> which is represented by total milliseconds count passed since 1970</returns>
|
|
||||||
public static long ToUnixTime(this DateTime dt) =>
|
|
||||||
(long)dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
|
||||||
|
|
||||||
public static void SetContent(this HttpRequestMessage request, params (string key, string value)[] values)
|
|
||||||
{
|
|
||||||
if (request == null)
|
|
||||||
throw new ArgumentNullException(nameof(request));
|
|
||||||
|
|
||||||
Dictionary<string, string> body = new Dictionary<string, string>();
|
|
||||||
foreach ((string key, string value) in values)
|
|
||||||
body.Add(key, value);
|
|
||||||
request.Content = new FormUrlEncodedContent(body);
|
|
||||||
}
|
|
||||||
public static async Task<string> GetString(this HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
if (response == null)
|
|
||||||
throw new ArgumentNullException(nameof(response));
|
|
||||||
|
|
||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
|
||||||
return Encoding.GetEncoding("Windows-1251").GetString(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Android.OS;
|
|
||||||
using Android.Widget;
|
|
||||||
using Android.App;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Android.Content;
|
|
||||||
|
|
||||||
namespace GUT.Schedule
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Date picker
|
|
||||||
/// </summary>
|
|
||||||
public class DatePickerFragment : Android.Support.V4.App.DialogFragment, DatePickerDialog.IOnDateSetListener
|
|
||||||
{
|
|
||||||
DateTime _date;
|
|
||||||
bool dismissed = false;
|
|
||||||
public override Dialog OnCreateDialog(Bundle savedInstanceState) =>
|
|
||||||
new DatePickerDialog(Activity, this, _date.Year, _date.Month - 1, _date.Day);
|
|
||||||
|
|
||||||
// Occures when user selected a date
|
|
||||||
public void OnDateSet(DatePicker view, int year, int month, int dayOfMonth)
|
|
||||||
{
|
|
||||||
_date = view.DateTime;
|
|
||||||
dismissed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnCancel(IDialogInterface dialog)
|
|
||||||
{
|
|
||||||
base.OnCancel(dialog);
|
|
||||||
dismissed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shows date picker and waits for user input
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="manager">Fragment manager of the current activity (In most common cases it is <c>this.FragmentManager</c>)</param>
|
|
||||||
/// <param name="date">Date which is to be selected by default</param>
|
|
||||||
/// <returns><see cref="DateTime"/> picked by user</returns>
|
|
||||||
public async Task<DateTime> GetDate(Android.Support.V4.App.FragmentManager manager, DateTime date)
|
|
||||||
{
|
|
||||||
_date = date;
|
|
||||||
Show(manager, "datePicker");
|
|
||||||
|
|
||||||
while (!dismissed)
|
|
||||||
await Task.Delay(100);
|
|
||||||
|
|
||||||
return _date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Models
|
|
||||||
{
|
|
||||||
public class CabinetSubject
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string Cabinet { get; set; }
|
|
||||||
public string Order { get; set; }
|
|
||||||
public DateTime StartTime { get; set; }
|
|
||||||
public DateTime EndTime { get; set; }
|
|
||||||
public string Opponent { get; set; }
|
|
||||||
public bool ProfessorSchedule { get; set; }
|
|
||||||
|
|
||||||
public CabinetSubject(string name, string type, string cabinet, string opponent, int year, int month, int day, string schedule, bool profSchedule)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Type = type;
|
|
||||||
Cabinet = cabinet;
|
|
||||||
Opponent = opponent;
|
|
||||||
ProfessorSchedule = profSchedule;
|
|
||||||
|
|
||||||
string[] time = schedule.Split('-');
|
|
||||||
|
|
||||||
StartTime = new DateTime(year, month, day, int.Parse(time[0].Split('.')[0]), int.Parse(time[0].Split('.')[1]), 0);
|
|
||||||
EndTime = new DateTime(year, month, day, int.Parse(time[1].Split('.')[0]), int.Parse(time[1].Split('.')[1]), 0);
|
|
||||||
Order = time[0] switch
|
|
||||||
{
|
|
||||||
"09.00" => "1",
|
|
||||||
"10.45" => "2",
|
|
||||||
"13.00" => "3",
|
|
||||||
"14.45" => "4",
|
|
||||||
"16.30" => "5",
|
|
||||||
"18.15" => "6",
|
|
||||||
"20.00" => "7",
|
|
||||||
"10.30" => "2", //Расписание для пар по физ-ре
|
|
||||||
"12.00" => "3",
|
|
||||||
"13.30" => "4",
|
|
||||||
"15.00" => "5",
|
|
||||||
"18.00" => "7",
|
|
||||||
_ => ""
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using GUT.Schedule.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace GUT.Schedule
|
|
||||||
{
|
|
||||||
public static class Data
|
|
||||||
{
|
|
||||||
public static List<(string Id, string Name)> Faculties { get; set; }
|
|
||||||
public static List<(string Id, string Name)> Groups { get; set; }
|
|
||||||
public static int FirstWeekDay { get; set; }
|
|
||||||
public static DateTime StartDate { get; set; } = DateTime.Today;
|
|
||||||
public static DateTime EndDate { get; set; } = DateTime.Today.AddDays(7);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Export parameters
|
|
||||||
/// </summary>
|
|
||||||
public static DataSet DataSet { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Models
|
|
||||||
{
|
|
||||||
public class DataSet
|
|
||||||
{
|
|
||||||
public string Calendar { get; set; }
|
|
||||||
public string Faculty { get; set; }
|
|
||||||
public int Course { get; set; }
|
|
||||||
public string Group { get; set; }
|
|
||||||
public int Reminder { get; set; }
|
|
||||||
public bool AddGroupToTitle { get; set; }
|
|
||||||
public HttpClient HttpClient { get; set; }
|
|
||||||
public bool? IsProfessor { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace GUT.Schedule.Models
|
|
||||||
{
|
|
||||||
public class Subject
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string Professor { get; set; }
|
|
||||||
public string[] Cabinets { get; set; }
|
|
||||||
public string Order { get; set; }
|
|
||||||
public DateTime StartTime { get; set; }
|
|
||||||
public DateTime EndTime { get; set; }
|
|
||||||
public string Group { get; set; }
|
|
||||||
|
|
||||||
public static List<Subject> GetSubject(string name, string type, string professor, string place, int order, string[] weeks, int weekday, string group)
|
|
||||||
{
|
|
||||||
List<Subject> subjects = new List<Subject>();
|
|
||||||
string[] cabinets = place.Replace("ауд.: ", "").Replace("; Б22", "").Split(';');
|
|
||||||
string pair = order < 10 ? order.ToString() : $"Ф{order - 81}";
|
|
||||||
|
|
||||||
foreach (string week in weeks)
|
|
||||||
subjects.Add(new Subject(name, type, professor, cabinets, pair, int.Parse(week), weekday, group));
|
|
||||||
|
|
||||||
return subjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Subject(string name, string type, string prof, string[] cabs, string order, int week, int weekday, string group)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Type = type;
|
|
||||||
Professor = prof;
|
|
||||||
Cabinets = cabs;
|
|
||||||
Order = order;
|
|
||||||
Group = group;
|
|
||||||
|
|
||||||
StartTime = Extensions.GetDateFromWeeks(week, weekday);
|
|
||||||
StartTime = StartTime.Add(TimeSpan.Parse(order switch
|
|
||||||
{
|
|
||||||
"1" => "9:00",
|
|
||||||
"2" => "10:45",
|
|
||||||
"3" => "13:00",
|
|
||||||
"4" => "14:45",
|
|
||||||
"5" => "16:30",
|
|
||||||
"6" => "18:15",
|
|
||||||
"7" => "20:00",
|
|
||||||
"Ф1" => "9:00", //Расписание для пар по физ-ре
|
|
||||||
"Ф2" => "10:30",
|
|
||||||
"Ф3" => "12:00",
|
|
||||||
"Ф4" => "13:30",
|
|
||||||
"Ф5" => "15:00",
|
|
||||||
"Ф6" => "16:30",
|
|
||||||
"Ф7" => "18:00",
|
|
||||||
_ => "9:00"
|
|
||||||
}));
|
|
||||||
EndTime = StartTime + TimeSpan.FromMinutes(order.Contains("Ф") ? 90 : 95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
using AngleSharp.Dom;
|
|
||||||
using AngleSharp.Html.Dom;
|
|
||||||
using AngleSharp.Html.Parser;
|
|
||||||
using GUT.Schedule.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace GUT.Schedule
|
|
||||||
{
|
|
||||||
public static class Parser
|
|
||||||
{
|
|
||||||
public static async Task<List<Subject>> LoadSchedule()
|
|
||||||
{
|
|
||||||
List<Subject> schedule = new List<Subject>();
|
|
||||||
using HttpClient client = new HttpClient();
|
|
||||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "group_el", "0" },
|
|
||||||
{ "kurs", Data.DataSet.Course.ToString() },
|
|
||||||
{ "type_z", "1" },
|
|
||||||
{ "faculty", Data.DataSet.Faculty },
|
|
||||||
{ "group", Data.DataSet.Group },
|
|
||||||
{ "ok", "Показать" },
|
|
||||||
{ "schet", GetCurrentSemester() }
|
|
||||||
};
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new")
|
|
||||||
{
|
|
||||||
Content = new FormUrlEncodedContent(requestBody)
|
|
||||||
};
|
|
||||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
|
|
||||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await response.Content.ReadAsStringAsync());
|
|
||||||
|
|
||||||
string groupName = Data.Groups.First(i => i.Id == Data.DataSet.Group).Name;
|
|
||||||
|
|
||||||
IHtmlCollection<IElement> pairs = doc.QuerySelectorAll(".pair");
|
|
||||||
foreach (IElement item in pairs)
|
|
||||||
{
|
|
||||||
string name, type, professor, place;
|
|
||||||
int order, weekday;
|
|
||||||
string[] weeks;
|
|
||||||
|
|
||||||
name = item.QuerySelector(".subect strong")?.TextContent ?? "Неизвестный предмет (см. Расписание)";
|
|
||||||
type = item.QuerySelector(".type").TextContent.Replace("(", "").Replace(")", "");
|
|
||||||
professor = item.QuerySelector(".teacher")?.GetAttribute("title").Replace(";", "") ?? "";
|
|
||||||
place = item.QuerySelector(".aud")?.TextContent ?? "СПбГУТ";
|
|
||||||
order = int.Parse(item.GetAttribute("pair")) - 1;
|
|
||||||
weeks = item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Split(", ");
|
|
||||||
weekday = int.Parse(item.GetAttribute("weekday"));
|
|
||||||
|
|
||||||
schedule.AddRange(Subject.GetSubject(name, type, professor, place, order, weeks, weekday, groupName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return schedule;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task LoadFaculties()
|
|
||||||
{
|
|
||||||
Data.Faculties = new List<(string, string)>();
|
|
||||||
using HttpClient client = new HttpClient();
|
|
||||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "choice", "1" },
|
|
||||||
{ "kurs", "0" },
|
|
||||||
{ "type_z", "1" },
|
|
||||||
{ "schet", GetCurrentSemester() }
|
|
||||||
};
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
|
||||||
{
|
|
||||||
Content = new FormUrlEncodedContent(requestBody)
|
|
||||||
};
|
|
||||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
string responseBody = await response.Content.ReadAsStringAsync();
|
|
||||||
if (string.IsNullOrWhiteSpace(responseBody))
|
|
||||||
throw new NullReferenceException("Расписание на текущий семестр еще не объявлено");
|
|
||||||
|
|
||||||
foreach (string s in responseBody.Split(';'))
|
|
||||||
try { Data.Faculties.Add((s.Split(',')[0], s.Split(',')[1])); }
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task LoadGroups(string facultyId, int course)
|
|
||||||
{
|
|
||||||
using HttpClient client = new HttpClient();
|
|
||||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "choice", "1" },
|
|
||||||
{ "kurs", course.ToString() },
|
|
||||||
{ "type_z", "1" },
|
|
||||||
{ "faculty", facultyId },
|
|
||||||
{ "schet", GetCurrentSemester() }
|
|
||||||
};
|
|
||||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
|
||||||
{
|
|
||||||
Content = new FormUrlEncodedContent(requestBody)
|
|
||||||
};
|
|
||||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
string responseBody = await response.Content.ReadAsStringAsync();
|
|
||||||
Data.Groups = new List<(string, string)>();
|
|
||||||
foreach (string s in responseBody.Split(';'))
|
|
||||||
try { Data.Groups.Add((s.Split(',')[0], s.Split(',')[1])); }
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetCurrentSemester()
|
|
||||||
{
|
|
||||||
DateTime now = DateTime.Today;
|
|
||||||
|
|
||||||
if (now.Month > 8)
|
|
||||||
return $"205.{now.Year - 2000}{now.Year - 1999}/1";
|
|
||||||
else
|
|
||||||
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<CabinetSubject>> GetCabinetSchedule(HttpClient client, DateTime date, bool checkProfSchedule)
|
|
||||||
{
|
|
||||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"https://cabs.itut.ru/cabinet/project/cabinet/forms/{(checkProfSchedule ? "pr_" : "")}raspisanie_kalendar.php");
|
|
||||||
request.SetContent(
|
|
||||||
("month", date.Month.ToString()),
|
|
||||||
("year", date.Year.ToString()),
|
|
||||||
("type_z", "0"));
|
|
||||||
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
|
|
||||||
string responseContent = await response.GetString().ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
throw new HttpRequestException(responseContent);
|
|
||||||
|
|
||||||
IHtmlDocument doc = new HtmlParser().ParseDocument(responseContent);
|
|
||||||
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
|
||||||
|
|
||||||
if(!checkProfSchedule)
|
|
||||||
Data.DataSet.Group = doc.QuerySelector(".style_gr b").TextContent;
|
|
||||||
|
|
||||||
foreach (var i in doc.QuerySelectorAll("td").Where(i => i.GetAttribute("style") == "text-align: center; vertical-align: top"))
|
|
||||||
for (int k = 0; k < i.QuerySelectorAll("i").Length; k++)
|
|
||||||
{
|
|
||||||
CabinetSubject item = new CabinetSubject(
|
|
||||||
name: i.QuerySelectorAll("b")[k * 2 + 1].TextContent,
|
|
||||||
type: i.QuerySelectorAll("i")[k].TextContent,
|
|
||||||
cabinet: i.QuerySelectorAll("small")[k].NextSibling.TextContent.Replace("; Б22", ""),
|
|
||||||
opponent: i.QuerySelectorAll("i")[k].NextSibling.NextSibling.NodeType == NodeType.Text ?
|
|
||||||
i.QuerySelectorAll("i")[k].NextSibling.NextSibling.TextContent : "",
|
|
||||||
year: date.Year,
|
|
||||||
month: date.Month,
|
|
||||||
day: int.Parse(i.ChildNodes[0].TextContent),
|
|
||||||
schedule: i.QuerySelectorAll("b")[k * 2 + 2].TextContent,
|
|
||||||
checkProfSchedule);
|
|
||||||
schedule.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge duplicating entries
|
|
||||||
schedule.OrderByDescending(i => i.StartTime);
|
|
||||||
for(int k = 1; k < schedule.Count; k++)
|
|
||||||
if(schedule[k - 1].StartTime == schedule[k].StartTime &&
|
|
||||||
schedule[k - 1].Name == schedule[k].Name &&
|
|
||||||
schedule[k - 1].Type == schedule[k].Type)
|
|
||||||
{
|
|
||||||
schedule[k - 1].Opponent += "\n" + schedule[k].Opponent;
|
|
||||||
schedule[k - 1].Cabinet += "; " + schedule[k].Cabinet;
|
|
||||||
schedule.RemoveAt(k--);
|
|
||||||
}
|
|
||||||
|
|
||||||
return schedule;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Support.V4.Text;
|
||||||
|
using Android.Support.V7.App;
|
||||||
|
using Android.Text.Method;
|
||||||
|
using Android.Widget;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid.Activities
|
||||||
|
{
|
||||||
|
[Activity(Label = "@string/aboutTitle")]
|
||||||
|
public class AboutActivity : AppCompatActivity
|
||||||
|
{
|
||||||
|
protected override async void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
(string name, string handle, string link)[] contacts = new (string, string, string)[]
|
||||||
|
{
|
||||||
|
(Resources.GetText(Resource.String.websiteContact), "https://xfox111.net", "https://xfox111.net"),
|
||||||
|
(Resources.GetText(Resource.String.twitterContact), "@xfox111", "https://twitter.com/xfox111"),
|
||||||
|
(Resources.GetText(Resource.String.vkontakteContact), "@xfox.mike", "https://vk.com/xfox.mike"),
|
||||||
|
("LinkedIn", "@xfox", "https://linkedin.com/in/xfox"),
|
||||||
|
("GitHub", "@xfox111", "https://github.com/xfox111"),
|
||||||
|
};
|
||||||
|
(string name, string link)[] links = new (string, string)[]
|
||||||
|
{
|
||||||
|
(Resources.GetText(Resource.String.privacyPolicyLink), "https://xfox111.net/Projects/GUTSchedule/PrivacyPolicy.txt"),
|
||||||
|
("General Public License v3", "https://www.gnu.org/licenses/gpl-3.0"),
|
||||||
|
(Resources.GetText(Resource.String.repositoryLink), "https://github.com/xfox111/gutschedule"),
|
||||||
|
(Resources.GetText(Resource.String.notsLink), "http://tios.spbgut.ru/index.php"),
|
||||||
|
(Resources.GetText(Resource.String.sutLink), "https://sut.ru"),
|
||||||
|
};
|
||||||
|
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
SetContentView(Resource.Layout.About);
|
||||||
|
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||||
|
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||||
|
|
||||||
|
FindViewById<Button>(Resource.Id.feedback).Click += (s, e) =>
|
||||||
|
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
||||||
|
|
||||||
|
FindViewById<TextView>(Resource.Id.contacts).SetText(
|
||||||
|
HtmlCompat.FromHtml(string.Join("<br />", contacts.Select(i => $"<span>{i.name}:</span> <a href=\"{i.link}\">{i.handle}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||||
|
TextView.BufferType.Normal);
|
||||||
|
FindViewById<TextView>(Resource.Id.contacts).MovementMethod = LinkMovementMethod.Instance;
|
||||||
|
|
||||||
|
FindViewById<TextView>(Resource.Id.links).SetText(
|
||||||
|
HtmlCompat.FromHtml(string.Join("<br />", links.Select(i => $"<a href=\"{i.link}\">{i.name}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||||
|
TextView.BufferType.Normal);
|
||||||
|
FindViewById<TextView>(Resource.Id.links).MovementMethod = LinkMovementMethod.Instance;
|
||||||
|
|
||||||
|
List<string> contributors = new List<string>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using HttpClient client = new HttpClient();
|
||||||
|
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/xfox111/gutschedule/contributors");
|
||||||
|
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request);
|
||||||
|
string resposeContent = await response.Content.ReadAsStringAsync();
|
||||||
|
dynamic parsedResponse = JsonConvert.DeserializeObject(resposeContent);
|
||||||
|
|
||||||
|
foreach (var i in parsedResponse)
|
||||||
|
if (i.type == "User" && ((string)i.login).ToLower() != "xfox111")
|
||||||
|
contributors.Add((string)i.login);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (contributors.Count > 0)
|
||||||
|
{
|
||||||
|
FindViewById<TextView>(Resource.Id.contributors).SetText(
|
||||||
|
HtmlCompat.FromHtml(string.Join(", ", contributors.Select(i => $"<a href=\"https://github.com/{i}\">@{i}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||||
|
TextView.BufferType.Normal);
|
||||||
|
FindViewById<TextView>(Resource.Id.contributors).MovementMethod = LinkMovementMethod.Instance;
|
||||||
|
|
||||||
|
FindViewById<TextView>(Resource.Id.contributorsTitle).Visibility = Android.Views.ViewStates.Visible;
|
||||||
|
FindViewById<TextView>(Resource.Id.contributors).Visibility = Android.Views.ViewStates.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Widget;
|
||||||
|
using GUTSchedule.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid.Activities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Shows status of schedule export process
|
||||||
|
/// </summary>
|
||||||
|
[Activity(Theme = "@style/AppTheme.Light.SplashScreen")]
|
||||||
|
public class ExportActivity : Activity
|
||||||
|
{
|
||||||
|
TextView status;
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
SetContentView(Resource.Layout.Export);
|
||||||
|
|
||||||
|
status = FindViewById<TextView>(Resource.Id.status);
|
||||||
|
|
||||||
|
Export();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Export()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Data.DataSet.IsProfessor == true)
|
||||||
|
status.Text = Resources.GetText(Resource.String.potatoLoadingStatus); // For some reason professors' schedule loads much slower
|
||||||
|
else
|
||||||
|
status.Text = Resources.GetText(Resource.String.loadingStatus);
|
||||||
|
|
||||||
|
if (Data.DataSet.HttpClient != null)
|
||||||
|
{
|
||||||
|
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
||||||
|
|
||||||
|
for (DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
||||||
|
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, false)); // Even though the user can be professor he can be also PhD student (and have his student schedule)
|
||||||
|
|
||||||
|
if (Data.DataSet.IsProfessor == true)
|
||||||
|
for (DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
||||||
|
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, true));
|
||||||
|
|
||||||
|
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
||||||
|
Calendar.Export(schedule);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Subject> schedule = await Parser.LoadSchedule();
|
||||||
|
|
||||||
|
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
||||||
|
Calendar.Export(schedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.doneStatus);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||||
|
builder.SetMessage(Resources.GetText(Resource.String.connectionFailMessage))
|
||||||
|
.SetTitle(e.Message)
|
||||||
|
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed())
|
||||||
|
.SetNegativeButton(Resources.GetText(Resource.String.repeat), (s, e) => Export());
|
||||||
|
|
||||||
|
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||||
|
dialog.Show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||||
|
builder.SetMessage(e.Message)
|
||||||
|
.SetTitle(e.GetType().ToString())
|
||||||
|
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed());
|
||||||
|
|
||||||
|
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||||
|
dialog.Show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base.OnBackPressed(); // Navigates back to main activity (always because I don't allow backward navigation)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnBackPressed() { } // Disables back button
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Preferences;
|
||||||
|
using Android.Support.V7.App;
|
||||||
|
using Android.Text.Method;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Widget;
|
||||||
|
using AngleSharp.Html.Dom;
|
||||||
|
using AngleSharp.Html.Parser;
|
||||||
|
using GUTSchedule.Models;
|
||||||
|
using GUTSchedule;
|
||||||
|
using GUTSchedule.Droid.Fragments;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid.Activities
|
||||||
|
{
|
||||||
|
[Activity]
|
||||||
|
public class MainActivity : AppCompatActivity
|
||||||
|
{
|
||||||
|
Button start, end, export;
|
||||||
|
Button forDay, forWeek, forMonth, forSemester;
|
||||||
|
Spinner faculty, course, group, reminder, calendar;
|
||||||
|
CheckBox groupTitle, authorize;
|
||||||
|
TextView error;
|
||||||
|
LinearLayout studentParams, profParams;
|
||||||
|
EditText email, password;
|
||||||
|
|
||||||
|
ISharedPreferences prefs;
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
SetContentView(Resource.Layout.Main);
|
||||||
|
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||||
|
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||||
|
|
||||||
|
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||||
|
|
||||||
|
AssignVariables();
|
||||||
|
|
||||||
|
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
||||||
|
int s = Data.Faculties.FindIndex(i => i.Id == prefs.GetString("Faculty", "-123"));
|
||||||
|
faculty.SetSelection(s == -1 ? 0 : s);
|
||||||
|
|
||||||
|
course.SetList(this, "1234".ToCharArray());
|
||||||
|
course.SetSelection(prefs.GetInt("Course", 0)); // IDK why but this shit triggers events anyway (even if they are set in the next line. It seem to be that there's some asynchronous shit somewhere there)
|
||||||
|
// P.S. Fuck Android
|
||||||
|
|
||||||
|
AddEvents();
|
||||||
|
|
||||||
|
// Settings spinners' dropdown lists content
|
||||||
|
reminder.SetList(this, new[]
|
||||||
|
{
|
||||||
|
Resources.GetText(Resource.String.noReminderOption),
|
||||||
|
Resources.GetText(Resource.String.inTimeReminderOption),
|
||||||
|
Resources.GetText(Resource.String.fiveMinuteReminderOption),
|
||||||
|
Resources.GetText(Resource.String.tenMinuteReminderOption)
|
||||||
|
});
|
||||||
|
reminder.SetSelection(prefs.GetInt("Reminder", 0));
|
||||||
|
|
||||||
|
calendar.SetList(this, Calendar.Calendars.Select(i => i.Name));
|
||||||
|
s = Calendar.Calendars.FindIndex(i => i.Id == prefs.GetString("Calendar", "-123"));
|
||||||
|
calendar.SetSelection(s == -1 ? 0 : s);
|
||||||
|
|
||||||
|
end.Text = Data.EndDate.ToShortDateString();
|
||||||
|
start.Text = Data.StartDate.ToShortDateString();
|
||||||
|
|
||||||
|
groupTitle.Checked = prefs.GetBoolean("AddGroupToHeader", false);
|
||||||
|
authorize.Checked = prefs.GetBoolean("Authorize", true);
|
||||||
|
|
||||||
|
email.Text = prefs.GetString("email", "");
|
||||||
|
password.Text = prefs.GetString("password", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Export_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
error.Visibility = ViewStates.Gone;
|
||||||
|
|
||||||
|
if (Data.StartDate > Data.EndDate)
|
||||||
|
{
|
||||||
|
error.Text = Resources.GetText(Resource.String.invalidDateRangeError);
|
||||||
|
error.Visibility = ViewStates.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient client = null;
|
||||||
|
bool? isProf = null;
|
||||||
|
if (authorize.Checked)
|
||||||
|
{
|
||||||
|
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.authorizationState), ToastLength.Short).Show();
|
||||||
|
if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text))
|
||||||
|
{
|
||||||
|
error.Text = Resources.GetText(Resource.String.invalidAuthorizationError);
|
||||||
|
error.Visibility = ViewStates.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
export.Enabled = false;
|
||||||
|
client = new HttpClient();
|
||||||
|
|
||||||
|
await client.GetAsync("https://cabs.itut.ru/cabinet/");
|
||||||
|
|
||||||
|
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php");
|
||||||
|
request.SetContent(
|
||||||
|
("users", email.Text),
|
||||||
|
("parole", password.Text));
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request);
|
||||||
|
string responseContent = await response.GetString();
|
||||||
|
export.Enabled = true;
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
error.Text = $"{Resources.GetText(Resource.String.authorizationError)}: {response.StatusCode}: {responseContent}";
|
||||||
|
error.Visibility = ViewStates.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
error.Text = $"{Resources.GetText(Resource.String.invalidCredentialError)} ({string.Join("; ", responseContent.Replace("error=", "", StringComparison.OrdinalIgnoreCase).Split('|'))})";
|
||||||
|
error.Visibility = ViewStates.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
export.Enabled = false;
|
||||||
|
HttpResponseMessage verificationResponse = await client.GetAsync("https://cabs.itut.ru/cabinet/?login=yes");
|
||||||
|
export.Enabled = true;
|
||||||
|
IHtmlDocument doc = new HtmlParser().ParseDocument(await verificationResponse.GetString());
|
||||||
|
if (doc.QuerySelectorAll("option").Any(i => i.TextContent.Contains("Сотрудник")))
|
||||||
|
isProf = true;
|
||||||
|
else
|
||||||
|
isProf = false;
|
||||||
|
|
||||||
|
Data.Groups = null;
|
||||||
|
|
||||||
|
// Если ты это читаешь и у тебя возникли вопросы по типу "А какого хуя творится в коде ниже?!", то во-первых:
|
||||||
|
// According to this SO thread: https://stackoverflow.com/questions/1925486/android-storing-username-and-password
|
||||||
|
// I consider Preferences as safe enough method for storing credentials
|
||||||
|
// А во-вторых, даже такой казалось бы небезопасный метод хранения учетных данных в сто раз надежнее того дерьма,
|
||||||
|
// что творится на серверах Бонча (я не шучу, там все ОЧЕНЬ плохо)
|
||||||
|
// Ну и в-третьих: Андроид - это пиздец и настоящий ад разработчика. И если бы была моя воля, я бы под него никогда не писал #FuckAndroid
|
||||||
|
// З.Ы. Помнишь про второй пункт? Так вот, если ты используешь такой же пароль как в ЛК где-то еще, настоятельно рекомендую его поменять
|
||||||
|
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("email", email.Text).Apply();
|
||||||
|
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("password", password.Text).Apply();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Data.Groups.Count < 1)
|
||||||
|
{
|
||||||
|
error.Text = Resources.GetText(Resource.String.groupSelectionError);
|
||||||
|
error.Visibility = ViewStates.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forming export parameters
|
||||||
|
Data.DataSet = new DataSet
|
||||||
|
{
|
||||||
|
Faculty = Data.Faculties[faculty.SelectedItemPosition].Id,
|
||||||
|
Group = Data.Groups?[group.SelectedItemPosition].Id,
|
||||||
|
Course = course.SelectedItemPosition + 1,
|
||||||
|
AddGroupToTitle = groupTitle.Checked,
|
||||||
|
Calendar = Calendar.Calendars[calendar.SelectedItemPosition].Id,
|
||||||
|
Reminder = (reminder.SelectedItemPosition - 1) * 5,
|
||||||
|
HttpClient = client,
|
||||||
|
IsProfessor = isProf
|
||||||
|
};
|
||||||
|
|
||||||
|
StartActivity(new Intent(this, typeof(ExportActivity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void End_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Data.EndDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.EndDate);
|
||||||
|
end.Text = Data.EndDate.ToShortDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Start_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Data.StartDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.StartDate);
|
||||||
|
start.Text = Data.StartDate.ToShortDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void UpdateGroupsList()
|
||||||
|
{
|
||||||
|
if (course.SelectedItem == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1);
|
||||||
|
group.SetList(this, Data.Groups.Select(i => i.Name));
|
||||||
|
|
||||||
|
int s = Data.Groups?.FindIndex(i => i.Id == prefs.GetString("Group", "-123")) ?? 0;
|
||||||
|
group.SetSelection(s == -1 ? 0 : s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetDate(int days)
|
||||||
|
{
|
||||||
|
Data.EndDate = Data.StartDate.AddDays(days);
|
||||||
|
end.Text = Data.EndDate.ToShortDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Init stuff
|
||||||
|
private void AssignVariables()
|
||||||
|
{
|
||||||
|
start = FindViewById<Button>(Resource.Id.start);
|
||||||
|
end = FindViewById<Button>(Resource.Id.end);
|
||||||
|
export = FindViewById<Button>(Resource.Id.export);
|
||||||
|
|
||||||
|
forDay = FindViewById<Button>(Resource.Id.forDay);
|
||||||
|
forWeek = FindViewById<Button>(Resource.Id.forWeek);
|
||||||
|
forMonth = FindViewById<Button>(Resource.Id.forMonth);
|
||||||
|
forSemester = FindViewById<Button>(Resource.Id.forSemester);
|
||||||
|
|
||||||
|
faculty = FindViewById<Spinner>(Resource.Id.faculty);
|
||||||
|
course = FindViewById<Spinner>(Resource.Id.course);
|
||||||
|
group = FindViewById<Spinner>(Resource.Id.group);
|
||||||
|
reminder = FindViewById<Spinner>(Resource.Id.reminder);
|
||||||
|
calendar = FindViewById<Spinner>(Resource.Id.calendar);
|
||||||
|
|
||||||
|
error = FindViewById<TextView>(Resource.Id.error);
|
||||||
|
|
||||||
|
groupTitle = FindViewById<CheckBox>(Resource.Id.groupTitle);
|
||||||
|
authorize = FindViewById<CheckBox>(Resource.Id.authorization);
|
||||||
|
|
||||||
|
studentParams = FindViewById<LinearLayout>(Resource.Id.studentParams);
|
||||||
|
profParams = FindViewById<LinearLayout>(Resource.Id.professorParams);
|
||||||
|
|
||||||
|
email = FindViewById<EditText>(Resource.Id.email);
|
||||||
|
password = FindViewById<EditText>(Resource.Id.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddEvents()
|
||||||
|
{
|
||||||
|
faculty.ItemSelected += (s, e) =>
|
||||||
|
{
|
||||||
|
prefs.Edit().PutString("Faculty", Data.Faculties[e.Position].Id).Apply();
|
||||||
|
UpdateGroupsList();
|
||||||
|
};
|
||||||
|
course.ItemSelected += (s, e) =>
|
||||||
|
{
|
||||||
|
prefs.Edit().PutInt("Course", e.Position).Apply();
|
||||||
|
UpdateGroupsList();
|
||||||
|
};
|
||||||
|
authorize.CheckedChange += (s, e) =>
|
||||||
|
{
|
||||||
|
prefs.Edit().PutBoolean("Authorize", e.IsChecked).Apply();
|
||||||
|
if (e.IsChecked)
|
||||||
|
{
|
||||||
|
studentParams.Visibility = ViewStates.Gone;
|
||||||
|
profParams.Visibility = ViewStates.Visible;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
studentParams.Visibility = ViewStates.Visible;
|
||||||
|
profParams.Visibility = ViewStates.Gone;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
calendar.ItemSelected += (s, e) =>
|
||||||
|
prefs.Edit().PutString("Calendar", Calendar.Calendars[e.Position].Id).Apply();
|
||||||
|
reminder.ItemSelected += (s, e) =>
|
||||||
|
prefs.Edit().PutInt("Reminder", e.Position).Apply();
|
||||||
|
group.ItemSelected += (s, e) =>
|
||||||
|
prefs.Edit().PutString("Group", Data.Groups[e.Position].Id).Apply();
|
||||||
|
|
||||||
|
groupTitle.Click += (s, e) =>
|
||||||
|
prefs.Edit().PutBoolean("AddGroupToHeader", groupTitle.Checked).Apply();
|
||||||
|
|
||||||
|
|
||||||
|
forDay.Click += (s, e) => SetDate(0);
|
||||||
|
forWeek.Click += (s, e) => SetDate(6);
|
||||||
|
forMonth.Click += (s, e) => SetDate(30);
|
||||||
|
forSemester.Click += (s, e) =>
|
||||||
|
{
|
||||||
|
Data.EndDate = DateTime.Today.Month > 8 ? new DateTime(DateTime.Today.Year + 1, 1, 1) : new DateTime(DateTime.Today.Year, 8, 31);
|
||||||
|
end.Text = Data.EndDate.ToShortDateString();
|
||||||
|
};
|
||||||
|
|
||||||
|
start.Click += Start_Click;
|
||||||
|
end.Click += End_Click;
|
||||||
|
|
||||||
|
export.Click += Export_Click;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Menu stuff
|
||||||
|
public override bool OnCreateOptionsMenu(IMenu menu)
|
||||||
|
{
|
||||||
|
MenuInflater.Inflate(Resource.Menu.MainContextMenu, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(bool keepPrevious = true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.clearingStatus), ToastLength.Short).Show();
|
||||||
|
Calendar.Clear(keepPrevious);
|
||||||
|
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.doneStatus), ToastLength.Short).Show();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||||
|
builder.SetMessage(e.Message)
|
||||||
|
.SetTitle(e.GetType().ToString())
|
||||||
|
.SetPositiveButton("ОК", (IDialogInterfaceOnClickListener)null);
|
||||||
|
|
||||||
|
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||||
|
dialog.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnOptionsItemSelected(IMenuItem item)
|
||||||
|
{
|
||||||
|
Android.Support.V7.App.AlertDialog.Builder builder;
|
||||||
|
Android.Support.V7.App.AlertDialog dialog;
|
||||||
|
switch (item.ItemId)
|
||||||
|
{
|
||||||
|
case Resource.Id.about:
|
||||||
|
StartActivity(new Intent(this, typeof(AboutActivity)));
|
||||||
|
return true;
|
||||||
|
case Resource.Id.email:
|
||||||
|
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case Resource.Id.clear:
|
||||||
|
builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||||
|
builder.SetMessage(Resources.GetText(Resource.String.clearScheduleMessage))
|
||||||
|
.SetTitle(Resources.GetText(Resource.String.clearScheduleTitle))
|
||||||
|
.SetPositiveButton(Resources.GetText(Resource.String.clearUpcomingOption), (s, e) => Clear())
|
||||||
|
.SetNegativeButton(Resources.GetText(Resource.String.clearAllOption), (s, e) => Clear(false))
|
||||||
|
.SetNeutralButton(Resources.GetText(Resource.String.cancelOption), (IDialogInterfaceOnClickListener)null);
|
||||||
|
|
||||||
|
dialog = builder.Create();
|
||||||
|
dialog.Show();
|
||||||
|
|
||||||
|
// Making links clickable
|
||||||
|
dialog.FindViewById<TextView>(Android.Resource.Id.Message).MovementMethod = LinkMovementMethod.Instance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public override void OnBackPressed() =>
|
||||||
|
FinishAffinity(); // Close application
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Support.V4.App;
|
||||||
|
using Android.Support.V4.Content;
|
||||||
|
using Android.Support.V7.App;
|
||||||
|
using Android.Widget;
|
||||||
|
using GUTSchedule;
|
||||||
|
using GUTSchedule.Droid;
|
||||||
|
using GUTSchedule.Droid.Activities;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace GUT.Schedule.Droid.Activities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Splash screen activity. Loads init data
|
||||||
|
/// </summary>
|
||||||
|
[Activity(MainLauncher = true, Theme = "@style/AppTheme.Light.SplashScreen")]
|
||||||
|
public class StartActivity : AppCompatActivity
|
||||||
|
{
|
||||||
|
TextView status;
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
SetContentView(Resource.Layout.SplashScreen);
|
||||||
|
base.OnCreate(savedInstanceState);
|
||||||
|
|
||||||
|
status = FindViewById<TextView>(Resource.Id.status);
|
||||||
|
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||||
|
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.permissionsCheckStatus);
|
||||||
|
|
||||||
|
if (ContextCompat.CheckSelfPermission(this, Android.Manifest.Permission.WriteCalendar) != Permission.Granted)
|
||||||
|
{
|
||||||
|
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Android.Manifest.Permission.WriteCalendar))
|
||||||
|
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
||||||
|
else
|
||||||
|
RequestPermissions();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Proceed()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
status.Text = Resources.GetText(Resource.String.calendarLoadingStatus);
|
||||||
|
Calendar.LoadCalendars();
|
||||||
|
if (Calendar.Calendars.Count == 0)
|
||||||
|
{
|
||||||
|
ShowDialog(Resources.GetText(Resource.String.createCalendarTitle), Resources.GetText(Resource.String.createCalendarMessage));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.facultiesLoadingStatus);
|
||||||
|
await Parser.LoadFaculties();
|
||||||
|
|
||||||
|
status.Text = Resources.GetText(Resource.String.offsetDatesLoadingStatus);
|
||||||
|
using HttpClient client = new HttpClient();
|
||||||
|
Data.FirstWeekDay = int.Parse(await client.GetStringAsync("https://xfox111.net/schedule_offset.txt"));
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
ShowDialog(e.Message, Resources.GetText(Resource.String.connectionFailMessage), Proceed, FinishAndRemoveTask, Resources.GetText(Resource.String.repeat), Resources.GetText(Resource.String.quit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ShowDialog(e.GetType().ToString(), e.Message, FinishAndRemoveTask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StartActivity(new Intent(this, typeof(MainActivity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
|
||||||
|
{
|
||||||
|
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
|
||||||
|
if (grantResults.All(i => i == Permission.Granted))
|
||||||
|
Proceed();
|
||||||
|
else
|
||||||
|
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RequestPermissions() =>
|
||||||
|
ActivityCompat.RequestPermissions(this, new[]
|
||||||
|
{
|
||||||
|
Android.Manifest.Permission.ReadCalendar,
|
||||||
|
Android.Manifest.Permission.WriteCalendar,
|
||||||
|
Android.Manifest.Permission.Internet
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
private void ShowDialog(string title, string content, Action posAction = null, Action negAction = null, string posActionLabel = null, string negActionLabel = null)
|
||||||
|
{
|
||||||
|
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||||
|
builder.SetMessage(content)
|
||||||
|
.SetTitle(title).SetPositiveButton(posActionLabel ?? "OK", (s, e) => posAction?.Invoke());
|
||||||
|
|
||||||
|
if (negAction != null)
|
||||||
|
builder.SetNegativeButton(negActionLabel ?? Resources.GetText(Resource.String.close), (s, e) => negAction.Invoke());
|
||||||
|
|
||||||
|
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||||
|
dialog.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnBackPressed() { } // Disables back button
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Database;
|
||||||
|
using Android.Net;
|
||||||
|
using Android.Provider;
|
||||||
|
using GUTSchedule.Models;
|
||||||
|
using Java.Util;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid
|
||||||
|
{
|
||||||
|
public static class Calendar
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// List of all existing Google calendars on the device
|
||||||
|
/// </summary>
|
||||||
|
public static List<(string Id, string Name)> Calendars { get; private set; } = new List<(string Id, string Name)>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves all Google Accounts' calendars existing on the device and puts them to <see cref="Calendars"/>
|
||||||
|
/// </summary>
|
||||||
|
public static void LoadCalendars()
|
||||||
|
{
|
||||||
|
Calendars = new List<(string, string)>(); // Resetting current calendars list
|
||||||
|
|
||||||
|
// Building calendar data retrieval projections
|
||||||
|
Uri calendarsUri = CalendarContract.Calendars.ContentUri;
|
||||||
|
string[] calendarsProjection = {
|
||||||
|
CalendarContract.Calendars.InterfaceConsts.Id,
|
||||||
|
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
|
||||||
|
CalendarContract.Calendars.InterfaceConsts.AccountName
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retrieving calendars data
|
||||||
|
ICursor cursor = Application.Context.ContentResolver.Query(calendarsUri, calendarsProjection, null, null, null);
|
||||||
|
|
||||||
|
while (cursor.MoveToNext())
|
||||||
|
Calendars.Add((cursor.GetString(0), $"{cursor.GetString(1)} ({cursor.GetString(2)})"));
|
||||||
|
|
||||||
|
cursor.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Export(IEnumerable<Subject> schedule)
|
||||||
|
{
|
||||||
|
DataSet data = Data.DataSet;
|
||||||
|
|
||||||
|
foreach (Subject item in schedule)
|
||||||
|
{
|
||||||
|
ContentValues eventValues = new ContentValues();
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}.{1} {2} ({3})",
|
||||||
|
item.Order,
|
||||||
|
data.AddGroupToTitle ? $" [{item.Group}]" : "",
|
||||||
|
item.Name,
|
||||||
|
item.Type));
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Professor);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, string.Join(';', item.Cabinets));
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
||||||
|
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
||||||
|
|
||||||
|
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
||||||
|
|
||||||
|
// Settings reminder
|
||||||
|
if (data.Reminder != -5)
|
||||||
|
{
|
||||||
|
ContentValues reminderValues = new ContentValues();
|
||||||
|
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||||
|
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||||
|
|
||||||
|
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Export(IEnumerable<CabinetSubject> schedule)
|
||||||
|
{
|
||||||
|
DataSet data = Data.DataSet;
|
||||||
|
|
||||||
|
foreach (CabinetSubject item in schedule)
|
||||||
|
{
|
||||||
|
ContentValues eventValues = new ContentValues();
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}{1}. {2} ({3})",
|
||||||
|
item.ProfessorSchedule ? "📚 " : (data.AddGroupToTitle ? $"[{data.Group}] " : ""),
|
||||||
|
item.Order,
|
||||||
|
item.Name,
|
||||||
|
item.Type));
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Opponent);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, item.Cabinet);
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
||||||
|
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||||
|
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||||
|
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
||||||
|
|
||||||
|
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
||||||
|
|
||||||
|
// Settings reminder
|
||||||
|
if (data.Reminder != -5)
|
||||||
|
{
|
||||||
|
ContentValues reminderValues = new ContentValues();
|
||||||
|
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||||
|
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||||
|
|
||||||
|
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Clear(bool keepPrevious = true)
|
||||||
|
{
|
||||||
|
Uri contentUri = CalendarContract.Events.ContentUri;
|
||||||
|
string selector = $"({CalendarContract.Events.InterfaceConsts.CustomAppPackage} == \"{Application.Context.PackageName}\") AND (deleted != 1)";
|
||||||
|
if (keepPrevious)
|
||||||
|
selector += $" AND (dtstart > {System.DateTime.Now.ToUnixTime()})";
|
||||||
|
|
||||||
|
string[] calendarsProjection = {
|
||||||
|
CalendarContract.Events.InterfaceConsts.Id,
|
||||||
|
CalendarContract.Events.InterfaceConsts.Dtstart,
|
||||||
|
CalendarContract.Events.InterfaceConsts.CustomAppPackage,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retrieving calendars data
|
||||||
|
ICursor cursor = Application.Context.ContentResolver.Query(contentUri, calendarsProjection, selector, null, null);
|
||||||
|
while (cursor.MoveToNext())
|
||||||
|
Application.Context.ContentResolver.Delete(ContentUris.WithAppendedId(CalendarContract.Events.ContentUri, cursor.GetLong(0)), null, null);
|
||||||
|
|
||||||
|
cursor.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Widget;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets array as Spinner dropdown list content
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Array items type</typeparam>
|
||||||
|
/// <param name="spinner">Spinner on which array will be assigned to</param>
|
||||||
|
/// <param name="context">Current activity context. In most common cases <c>this</c> will do</param>
|
||||||
|
/// <param name="array">Array of items to be displayed</param>
|
||||||
|
public static void SetList<T>(this Spinner spinner, Context context, IEnumerable<T> array)
|
||||||
|
{
|
||||||
|
ArrayAdapter adapter = new ArrayAdapter(context, Resource.Layout.support_simple_spinner_dropdown_item, array.ToList());
|
||||||
|
spinner.Adapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts <see cref="DateTime"/> to milliseconds count
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>In the nearest future we will be fucked because of that shit</remarks>
|
||||||
|
/// <param name="dt"><see cref="DateTime"/> which is to be converted to UNIX time</param>
|
||||||
|
/// <returns><see cref="long"/> which is represented by total milliseconds count passed since 1970</returns>
|
||||||
|
public static long ToUnixTime(this DateTime dt) =>
|
||||||
|
(long)dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Widget;
|
||||||
|
using Android.App;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Android.Content;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Droid.Fragments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Date picker
|
||||||
|
/// </summary>
|
||||||
|
public class DatePickerFragment : Android.Support.V4.App.DialogFragment, DatePickerDialog.IOnDateSetListener
|
||||||
|
{
|
||||||
|
DateTime _date;
|
||||||
|
bool dismissed = false;
|
||||||
|
public override Dialog OnCreateDialog(Bundle savedInstanceState) =>
|
||||||
|
new DatePickerDialog(Activity, this, _date.Year, _date.Month - 1, _date.Day);
|
||||||
|
|
||||||
|
// Occures when user selected a date
|
||||||
|
public void OnDateSet(DatePicker view, int year, int month, int dayOfMonth)
|
||||||
|
{
|
||||||
|
_date = view.DateTime;
|
||||||
|
dismissed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnCancel(IDialogInterface dialog)
|
||||||
|
{
|
||||||
|
base.OnCancel(dialog);
|
||||||
|
dismissed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows date picker and waits for user input
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="manager">Fragment manager of the current activity (In most common cases it is <c>this.FragmentManager</c>)</param>
|
||||||
|
/// <param name="date">Date which is to be selected by default</param>
|
||||||
|
/// <returns><see cref="DateTime"/> picked by user</returns>
|
||||||
|
public async Task<DateTime> GetDate(Android.Support.V4.App.FragmentManager manager, DateTime date)
|
||||||
|
{
|
||||||
|
_date = date;
|
||||||
|
Show(manager, "datePicker");
|
||||||
|
|
||||||
|
while (!dismissed)
|
||||||
|
await Task.Delay(100);
|
||||||
|
|
||||||
|
return _date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
<TemplateGuid>{84dd83c5-0fe3-4294-9419-09e7c8ba324f}</TemplateGuid>
|
<TemplateGuid>{84dd83c5-0fe3-4294-9419-09e7c8ba324f}</TemplateGuid>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>GUT.Schedule</RootNamespace>
|
<RootNamespace>GUTSchedule.Droid</RootNamespace>
|
||||||
<AssemblyName>GUT.Schedule</AssemblyName>
|
<AssemblyName>GUTSchedule.Droid</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AndroidApplication>True</AndroidApplication>
|
<AndroidApplication>True</AndroidApplication>
|
||||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||||
@@ -93,18 +93,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Activities\AboutActivity.cs" />
|
<Compile Include="Activities\AboutActivity.cs" />
|
||||||
<Compile Include="Calendar.cs" />
|
<Compile Include="Calendar.cs" />
|
||||||
<Compile Include="Models\Data.cs" />
|
|
||||||
<Compile Include="Fragments\DatePickerFragment.cs" />
|
<Compile Include="Fragments\DatePickerFragment.cs" />
|
||||||
<Compile Include="Activities\ExportActivity.cs" />
|
<Compile Include="Activities\ExportActivity.cs" />
|
||||||
<Compile Include="Extensions.cs" />
|
<Compile Include="Extensions.cs" />
|
||||||
<Compile Include="Activities\MainActivity.cs" />
|
<Compile Include="Activities\MainActivity.cs" />
|
||||||
<Compile Include="Models\DataSet.cs" />
|
|
||||||
<Compile Include="Models\CabinetSubject.cs" />
|
|
||||||
<Compile Include="Parser.cs" />
|
|
||||||
<Compile Include="Resources\Resource.designer.cs" />
|
<Compile Include="Resources\Resource.designer.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Activities\StartActivity.cs" />
|
<Compile Include="Activities\StartActivity.cs" />
|
||||||
<Compile Include="Models\Subject.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Properties\AndroidManifest.xml" />
|
<None Include="Properties\AndroidManifest.xml" />
|
||||||
@@ -133,9 +128,6 @@
|
|||||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp">
|
|
||||||
<Version>0.13.0</Version>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Microsoft.CSharp">
|
<PackageReference Include="Microsoft.CSharp">
|
||||||
<Version>4.7.0</Version>
|
<Version>4.7.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -174,15 +166,18 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Assets\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\values\strings.xml" />
|
<AndroidResource Include="Resources\values\strings.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\values-ru\strings.xml" />
|
<AndroidResource Include="Resources\values-ru\strings.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GUTSchedule\GUTSchedule.csproj">
|
||||||
|
<Project>{a6f6de35-0eb4-4d11-9ff9-f4601595b639}</Project>
|
||||||
|
<Name>GUTSchedule</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- 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.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
[assembly: global::Android.Runtime.ResourceDesignerAttribute("GUT.Schedule.Resource", IsApplication=true)]
|
[assembly: global::Android.Runtime.ResourceDesignerAttribute("GUTSchedule.Droid.Resource", IsApplication=true)]
|
||||||
|
|
||||||
namespace GUT.Schedule
|
namespace GUTSchedule.Droid
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -26,188 +26,188 @@ namespace GUT.Schedule
|
|||||||
|
|
||||||
public static void UpdateIdValues()
|
public static void UpdateIdValues()
|
||||||
{
|
{
|
||||||
global::Xamarin.Essentials.Resource.Attribute.alpha = global::GUT.Schedule.Resource.Attribute.alpha;
|
global::Xamarin.Essentials.Resource.Attribute.alpha = global::GUTSchedule.Droid.Resource.Attribute.alpha;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.coordinatorLayoutStyle = global::GUT.Schedule.Resource.Attribute.coordinatorLayoutStyle;
|
global::Xamarin.Essentials.Resource.Attribute.coordinatorLayoutStyle = global::GUTSchedule.Droid.Resource.Attribute.coordinatorLayoutStyle;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.font = global::GUT.Schedule.Resource.Attribute.font;
|
global::Xamarin.Essentials.Resource.Attribute.font = global::GUTSchedule.Droid.Resource.Attribute.font;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderAuthority = global::GUT.Schedule.Resource.Attribute.fontProviderAuthority;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderAuthority = global::GUTSchedule.Droid.Resource.Attribute.fontProviderAuthority;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderCerts = global::GUT.Schedule.Resource.Attribute.fontProviderCerts;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderCerts = global::GUTSchedule.Droid.Resource.Attribute.fontProviderCerts;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchStrategy = global::GUT.Schedule.Resource.Attribute.fontProviderFetchStrategy;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchStrategy = global::GUTSchedule.Droid.Resource.Attribute.fontProviderFetchStrategy;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchTimeout = global::GUT.Schedule.Resource.Attribute.fontProviderFetchTimeout;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchTimeout = global::GUTSchedule.Droid.Resource.Attribute.fontProviderFetchTimeout;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderPackage = global::GUT.Schedule.Resource.Attribute.fontProviderPackage;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderPackage = global::GUTSchedule.Droid.Resource.Attribute.fontProviderPackage;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderQuery = global::GUT.Schedule.Resource.Attribute.fontProviderQuery;
|
global::Xamarin.Essentials.Resource.Attribute.fontProviderQuery = global::GUTSchedule.Droid.Resource.Attribute.fontProviderQuery;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontStyle = global::GUT.Schedule.Resource.Attribute.fontStyle;
|
global::Xamarin.Essentials.Resource.Attribute.fontStyle = global::GUTSchedule.Droid.Resource.Attribute.fontStyle;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontVariationSettings = global::GUT.Schedule.Resource.Attribute.fontVariationSettings;
|
global::Xamarin.Essentials.Resource.Attribute.fontVariationSettings = global::GUTSchedule.Droid.Resource.Attribute.fontVariationSettings;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.fontWeight = global::GUT.Schedule.Resource.Attribute.fontWeight;
|
global::Xamarin.Essentials.Resource.Attribute.fontWeight = global::GUTSchedule.Droid.Resource.Attribute.fontWeight;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.keylines = global::GUT.Schedule.Resource.Attribute.keylines;
|
global::Xamarin.Essentials.Resource.Attribute.keylines = global::GUTSchedule.Droid.Resource.Attribute.keylines;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchor = global::GUT.Schedule.Resource.Attribute.layout_anchor;
|
global::Xamarin.Essentials.Resource.Attribute.layout_anchor = global::GUTSchedule.Droid.Resource.Attribute.layout_anchor;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchorGravity = global::GUT.Schedule.Resource.Attribute.layout_anchorGravity;
|
global::Xamarin.Essentials.Resource.Attribute.layout_anchorGravity = global::GUTSchedule.Droid.Resource.Attribute.layout_anchorGravity;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_behavior = global::GUT.Schedule.Resource.Attribute.layout_behavior;
|
global::Xamarin.Essentials.Resource.Attribute.layout_behavior = global::GUTSchedule.Droid.Resource.Attribute.layout_behavior;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_dodgeInsetEdges = global::GUT.Schedule.Resource.Attribute.layout_dodgeInsetEdges;
|
global::Xamarin.Essentials.Resource.Attribute.layout_dodgeInsetEdges = global::GUTSchedule.Droid.Resource.Attribute.layout_dodgeInsetEdges;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_insetEdge = global::GUT.Schedule.Resource.Attribute.layout_insetEdge;
|
global::Xamarin.Essentials.Resource.Attribute.layout_insetEdge = global::GUTSchedule.Droid.Resource.Attribute.layout_insetEdge;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.layout_keyline = global::GUT.Schedule.Resource.Attribute.layout_keyline;
|
global::Xamarin.Essentials.Resource.Attribute.layout_keyline = global::GUTSchedule.Droid.Resource.Attribute.layout_keyline;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.statusBarBackground = global::GUT.Schedule.Resource.Attribute.statusBarBackground;
|
global::Xamarin.Essentials.Resource.Attribute.statusBarBackground = global::GUTSchedule.Droid.Resource.Attribute.statusBarBackground;
|
||||||
global::Xamarin.Essentials.Resource.Attribute.ttcIndex = global::GUT.Schedule.Resource.Attribute.ttcIndex;
|
global::Xamarin.Essentials.Resource.Attribute.ttcIndex = global::GUTSchedule.Droid.Resource.Attribute.ttcIndex;
|
||||||
global::Xamarin.Essentials.Resource.Color.browser_actions_bg_grey = global::GUT.Schedule.Resource.Color.browser_actions_bg_grey;
|
global::Xamarin.Essentials.Resource.Color.browser_actions_bg_grey = global::GUTSchedule.Droid.Resource.Color.browser_actions_bg_grey;
|
||||||
global::Xamarin.Essentials.Resource.Color.browser_actions_divider_color = global::GUT.Schedule.Resource.Color.browser_actions_divider_color;
|
global::Xamarin.Essentials.Resource.Color.browser_actions_divider_color = global::GUTSchedule.Droid.Resource.Color.browser_actions_divider_color;
|
||||||
global::Xamarin.Essentials.Resource.Color.browser_actions_text_color = global::GUT.Schedule.Resource.Color.browser_actions_text_color;
|
global::Xamarin.Essentials.Resource.Color.browser_actions_text_color = global::GUTSchedule.Droid.Resource.Color.browser_actions_text_color;
|
||||||
global::Xamarin.Essentials.Resource.Color.browser_actions_title_color = global::GUT.Schedule.Resource.Color.browser_actions_title_color;
|
global::Xamarin.Essentials.Resource.Color.browser_actions_title_color = global::GUTSchedule.Droid.Resource.Color.browser_actions_title_color;
|
||||||
global::Xamarin.Essentials.Resource.Color.notification_action_color_filter = global::GUT.Schedule.Resource.Color.notification_action_color_filter;
|
global::Xamarin.Essentials.Resource.Color.notification_action_color_filter = global::GUTSchedule.Droid.Resource.Color.notification_action_color_filter;
|
||||||
global::Xamarin.Essentials.Resource.Color.notification_icon_bg_color = global::GUT.Schedule.Resource.Color.notification_icon_bg_color;
|
global::Xamarin.Essentials.Resource.Color.notification_icon_bg_color = global::GUTSchedule.Droid.Resource.Color.notification_icon_bg_color;
|
||||||
global::Xamarin.Essentials.Resource.Color.ripple_material_light = global::GUT.Schedule.Resource.Color.ripple_material_light;
|
global::Xamarin.Essentials.Resource.Color.ripple_material_light = global::GUTSchedule.Droid.Resource.Color.ripple_material_light;
|
||||||
global::Xamarin.Essentials.Resource.Color.secondary_text_default_material_light = global::GUT.Schedule.Resource.Color.secondary_text_default_material_light;
|
global::Xamarin.Essentials.Resource.Color.secondary_text_default_material_light = global::GUTSchedule.Droid.Resource.Color.secondary_text_default_material_light;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_max_width = global::GUT.Schedule.Resource.Dimension.browser_actions_context_menu_max_width;
|
global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_max_width = global::GUTSchedule.Droid.Resource.Dimension.browser_actions_context_menu_max_width;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_min_padding = global::GUT.Schedule.Resource.Dimension.browser_actions_context_menu_min_padding;
|
global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_min_padding = global::GUTSchedule.Droid.Resource.Dimension.browser_actions_context_menu_min_padding;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_horizontal_material = global::GUT.Schedule.Resource.Dimension.compat_button_inset_horizontal_material;
|
global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_horizontal_material = global::GUTSchedule.Droid.Resource.Dimension.compat_button_inset_horizontal_material;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_vertical_material = global::GUT.Schedule.Resource.Dimension.compat_button_inset_vertical_material;
|
global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_vertical_material = global::GUTSchedule.Droid.Resource.Dimension.compat_button_inset_vertical_material;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_horizontal_material = global::GUT.Schedule.Resource.Dimension.compat_button_padding_horizontal_material;
|
global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_horizontal_material = global::GUTSchedule.Droid.Resource.Dimension.compat_button_padding_horizontal_material;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_vertical_material = global::GUT.Schedule.Resource.Dimension.compat_button_padding_vertical_material;
|
global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_vertical_material = global::GUTSchedule.Droid.Resource.Dimension.compat_button_padding_vertical_material;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_control_corner_material = global::GUT.Schedule.Resource.Dimension.compat_control_corner_material;
|
global::Xamarin.Essentials.Resource.Dimension.compat_control_corner_material = global::GUTSchedule.Droid.Resource.Dimension.compat_control_corner_material;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_height = global::GUT.Schedule.Resource.Dimension.compat_notification_large_icon_max_height;
|
global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_height = global::GUTSchedule.Droid.Resource.Dimension.compat_notification_large_icon_max_height;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_width = global::GUT.Schedule.Resource.Dimension.compat_notification_large_icon_max_width;
|
global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_width = global::GUTSchedule.Droid.Resource.Dimension.compat_notification_large_icon_max_width;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_action_icon_size = global::GUT.Schedule.Resource.Dimension.notification_action_icon_size;
|
global::Xamarin.Essentials.Resource.Dimension.notification_action_icon_size = global::GUTSchedule.Droid.Resource.Dimension.notification_action_icon_size;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_action_text_size = global::GUT.Schedule.Resource.Dimension.notification_action_text_size;
|
global::Xamarin.Essentials.Resource.Dimension.notification_action_text_size = global::GUTSchedule.Droid.Resource.Dimension.notification_action_text_size;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_big_circle_margin = global::GUT.Schedule.Resource.Dimension.notification_big_circle_margin;
|
global::Xamarin.Essentials.Resource.Dimension.notification_big_circle_margin = global::GUTSchedule.Droid.Resource.Dimension.notification_big_circle_margin;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_content_margin_start = global::GUT.Schedule.Resource.Dimension.notification_content_margin_start;
|
global::Xamarin.Essentials.Resource.Dimension.notification_content_margin_start = global::GUTSchedule.Droid.Resource.Dimension.notification_content_margin_start;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_height = global::GUT.Schedule.Resource.Dimension.notification_large_icon_height;
|
global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_height = global::GUTSchedule.Droid.Resource.Dimension.notification_large_icon_height;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_width = global::GUT.Schedule.Resource.Dimension.notification_large_icon_width;
|
global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_width = global::GUTSchedule.Droid.Resource.Dimension.notification_large_icon_width;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_main_column_padding_top = global::GUT.Schedule.Resource.Dimension.notification_main_column_padding_top;
|
global::Xamarin.Essentials.Resource.Dimension.notification_main_column_padding_top = global::GUTSchedule.Droid.Resource.Dimension.notification_main_column_padding_top;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_media_narrow_margin = global::GUT.Schedule.Resource.Dimension.notification_media_narrow_margin;
|
global::Xamarin.Essentials.Resource.Dimension.notification_media_narrow_margin = global::GUTSchedule.Droid.Resource.Dimension.notification_media_narrow_margin;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_right_icon_size = global::GUT.Schedule.Resource.Dimension.notification_right_icon_size;
|
global::Xamarin.Essentials.Resource.Dimension.notification_right_icon_size = global::GUTSchedule.Droid.Resource.Dimension.notification_right_icon_size;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_right_side_padding_top = global::GUT.Schedule.Resource.Dimension.notification_right_side_padding_top;
|
global::Xamarin.Essentials.Resource.Dimension.notification_right_side_padding_top = global::GUTSchedule.Droid.Resource.Dimension.notification_right_side_padding_top;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_background_padding = global::GUT.Schedule.Resource.Dimension.notification_small_icon_background_padding;
|
global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_background_padding = global::GUTSchedule.Droid.Resource.Dimension.notification_small_icon_background_padding;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_size_as_large = global::GUT.Schedule.Resource.Dimension.notification_small_icon_size_as_large;
|
global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_size_as_large = global::GUTSchedule.Droid.Resource.Dimension.notification_small_icon_size_as_large;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_subtext_size = global::GUT.Schedule.Resource.Dimension.notification_subtext_size;
|
global::Xamarin.Essentials.Resource.Dimension.notification_subtext_size = global::GUTSchedule.Droid.Resource.Dimension.notification_subtext_size;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_top_pad = global::GUT.Schedule.Resource.Dimension.notification_top_pad;
|
global::Xamarin.Essentials.Resource.Dimension.notification_top_pad = global::GUTSchedule.Droid.Resource.Dimension.notification_top_pad;
|
||||||
global::Xamarin.Essentials.Resource.Dimension.notification_top_pad_large_text = global::GUT.Schedule.Resource.Dimension.notification_top_pad_large_text;
|
global::Xamarin.Essentials.Resource.Dimension.notification_top_pad_large_text = global::GUTSchedule.Droid.Resource.Dimension.notification_top_pad_large_text;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_action_background = global::GUT.Schedule.Resource.Drawable.notification_action_background;
|
global::Xamarin.Essentials.Resource.Drawable.notification_action_background = global::GUTSchedule.Droid.Resource.Drawable.notification_action_background;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg = global::GUT.Schedule.Resource.Drawable.notification_bg;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg = global::GUTSchedule.Droid.Resource.Drawable.notification_bg;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low = global::GUT.Schedule.Resource.Drawable.notification_bg_low;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low = global::GUTSchedule.Droid.Resource.Drawable.notification_bg_low;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_normal = global::GUT.Schedule.Resource.Drawable.notification_bg_low_normal;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_normal = global::GUTSchedule.Droid.Resource.Drawable.notification_bg_low_normal;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_pressed = global::GUT.Schedule.Resource.Drawable.notification_bg_low_pressed;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_pressed = global::GUTSchedule.Droid.Resource.Drawable.notification_bg_low_pressed;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal = global::GUT.Schedule.Resource.Drawable.notification_bg_normal;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal = global::GUTSchedule.Droid.Resource.Drawable.notification_bg_normal;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal_pressed = global::GUT.Schedule.Resource.Drawable.notification_bg_normal_pressed;
|
global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal_pressed = global::GUTSchedule.Droid.Resource.Drawable.notification_bg_normal_pressed;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_icon_background = global::GUT.Schedule.Resource.Drawable.notification_icon_background;
|
global::Xamarin.Essentials.Resource.Drawable.notification_icon_background = global::GUTSchedule.Droid.Resource.Drawable.notification_icon_background;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_bg = global::GUT.Schedule.Resource.Drawable.notification_template_icon_bg;
|
global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_bg = global::GUTSchedule.Droid.Resource.Drawable.notification_template_icon_bg;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_low_bg = global::GUT.Schedule.Resource.Drawable.notification_template_icon_low_bg;
|
global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_low_bg = global::GUTSchedule.Droid.Resource.Drawable.notification_template_icon_low_bg;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notification_tile_bg = global::GUT.Schedule.Resource.Drawable.notification_tile_bg;
|
global::Xamarin.Essentials.Resource.Drawable.notification_tile_bg = global::GUTSchedule.Droid.Resource.Drawable.notification_tile_bg;
|
||||||
global::Xamarin.Essentials.Resource.Drawable.notify_panel_notification_icon_bg = global::GUT.Schedule.Resource.Drawable.notify_panel_notification_icon_bg;
|
global::Xamarin.Essentials.Resource.Drawable.notify_panel_notification_icon_bg = global::GUTSchedule.Droid.Resource.Drawable.notify_panel_notification_icon_bg;
|
||||||
global::Xamarin.Essentials.Resource.Id.action_container = global::GUT.Schedule.Resource.Id.action_container;
|
global::Xamarin.Essentials.Resource.Id.action_container = global::GUTSchedule.Droid.Resource.Id.action_container;
|
||||||
global::Xamarin.Essentials.Resource.Id.action_divider = global::GUT.Schedule.Resource.Id.action_divider;
|
global::Xamarin.Essentials.Resource.Id.action_divider = global::GUTSchedule.Droid.Resource.Id.action_divider;
|
||||||
global::Xamarin.Essentials.Resource.Id.action_image = global::GUT.Schedule.Resource.Id.action_image;
|
global::Xamarin.Essentials.Resource.Id.action_image = global::GUTSchedule.Droid.Resource.Id.action_image;
|
||||||
global::Xamarin.Essentials.Resource.Id.action_text = global::GUT.Schedule.Resource.Id.action_text;
|
global::Xamarin.Essentials.Resource.Id.action_text = global::GUTSchedule.Droid.Resource.Id.action_text;
|
||||||
global::Xamarin.Essentials.Resource.Id.actions = global::GUT.Schedule.Resource.Id.actions;
|
global::Xamarin.Essentials.Resource.Id.actions = global::GUTSchedule.Droid.Resource.Id.actions;
|
||||||
global::Xamarin.Essentials.Resource.Id.all = global::GUT.Schedule.Resource.Id.all;
|
global::Xamarin.Essentials.Resource.Id.all = global::GUTSchedule.Droid.Resource.Id.all;
|
||||||
global::Xamarin.Essentials.Resource.Id.async = global::GUT.Schedule.Resource.Id.async;
|
global::Xamarin.Essentials.Resource.Id.async = global::GUTSchedule.Droid.Resource.Id.async;
|
||||||
global::Xamarin.Essentials.Resource.Id.blocking = global::GUT.Schedule.Resource.Id.blocking;
|
global::Xamarin.Essentials.Resource.Id.blocking = global::GUTSchedule.Droid.Resource.Id.blocking;
|
||||||
global::Xamarin.Essentials.Resource.Id.bottom = global::GUT.Schedule.Resource.Id.bottom;
|
global::Xamarin.Essentials.Resource.Id.bottom = global::GUTSchedule.Droid.Resource.Id.bottom;
|
||||||
global::Xamarin.Essentials.Resource.Id.browser_actions_header_text = global::GUT.Schedule.Resource.Id.browser_actions_header_text;
|
global::Xamarin.Essentials.Resource.Id.browser_actions_header_text = global::GUTSchedule.Droid.Resource.Id.browser_actions_header_text;
|
||||||
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_icon = global::GUT.Schedule.Resource.Id.browser_actions_menu_item_icon;
|
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_icon = global::GUTSchedule.Droid.Resource.Id.browser_actions_menu_item_icon;
|
||||||
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_text = global::GUT.Schedule.Resource.Id.browser_actions_menu_item_text;
|
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_text = global::GUTSchedule.Droid.Resource.Id.browser_actions_menu_item_text;
|
||||||
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_items = global::GUT.Schedule.Resource.Id.browser_actions_menu_items;
|
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_items = global::GUTSchedule.Droid.Resource.Id.browser_actions_menu_items;
|
||||||
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_view = global::GUT.Schedule.Resource.Id.browser_actions_menu_view;
|
global::Xamarin.Essentials.Resource.Id.browser_actions_menu_view = global::GUTSchedule.Droid.Resource.Id.browser_actions_menu_view;
|
||||||
global::Xamarin.Essentials.Resource.Id.center = global::GUT.Schedule.Resource.Id.center;
|
global::Xamarin.Essentials.Resource.Id.center = global::GUTSchedule.Droid.Resource.Id.center;
|
||||||
global::Xamarin.Essentials.Resource.Id.center_horizontal = global::GUT.Schedule.Resource.Id.center_horizontal;
|
global::Xamarin.Essentials.Resource.Id.center_horizontal = global::GUTSchedule.Droid.Resource.Id.center_horizontal;
|
||||||
global::Xamarin.Essentials.Resource.Id.center_vertical = global::GUT.Schedule.Resource.Id.center_vertical;
|
global::Xamarin.Essentials.Resource.Id.center_vertical = global::GUTSchedule.Droid.Resource.Id.center_vertical;
|
||||||
global::Xamarin.Essentials.Resource.Id.chronometer = global::GUT.Schedule.Resource.Id.chronometer;
|
global::Xamarin.Essentials.Resource.Id.chronometer = global::GUTSchedule.Droid.Resource.Id.chronometer;
|
||||||
global::Xamarin.Essentials.Resource.Id.clip_horizontal = global::GUT.Schedule.Resource.Id.clip_horizontal;
|
global::Xamarin.Essentials.Resource.Id.clip_horizontal = global::GUTSchedule.Droid.Resource.Id.clip_horizontal;
|
||||||
global::Xamarin.Essentials.Resource.Id.clip_vertical = global::GUT.Schedule.Resource.Id.clip_vertical;
|
global::Xamarin.Essentials.Resource.Id.clip_vertical = global::GUTSchedule.Droid.Resource.Id.clip_vertical;
|
||||||
global::Xamarin.Essentials.Resource.Id.end = global::GUT.Schedule.Resource.Id.end;
|
global::Xamarin.Essentials.Resource.Id.end = global::GUTSchedule.Droid.Resource.Id.end;
|
||||||
global::Xamarin.Essentials.Resource.Id.fill = global::GUT.Schedule.Resource.Id.fill;
|
global::Xamarin.Essentials.Resource.Id.fill = global::GUTSchedule.Droid.Resource.Id.fill;
|
||||||
global::Xamarin.Essentials.Resource.Id.fill_horizontal = global::GUT.Schedule.Resource.Id.fill_horizontal;
|
global::Xamarin.Essentials.Resource.Id.fill_horizontal = global::GUTSchedule.Droid.Resource.Id.fill_horizontal;
|
||||||
global::Xamarin.Essentials.Resource.Id.fill_vertical = global::GUT.Schedule.Resource.Id.fill_vertical;
|
global::Xamarin.Essentials.Resource.Id.fill_vertical = global::GUTSchedule.Droid.Resource.Id.fill_vertical;
|
||||||
global::Xamarin.Essentials.Resource.Id.forever = global::GUT.Schedule.Resource.Id.forever;
|
global::Xamarin.Essentials.Resource.Id.forever = global::GUTSchedule.Droid.Resource.Id.forever;
|
||||||
global::Xamarin.Essentials.Resource.Id.icon = global::GUT.Schedule.Resource.Id.icon;
|
global::Xamarin.Essentials.Resource.Id.icon = global::GUTSchedule.Droid.Resource.Id.icon;
|
||||||
global::Xamarin.Essentials.Resource.Id.icon_group = global::GUT.Schedule.Resource.Id.icon_group;
|
global::Xamarin.Essentials.Resource.Id.icon_group = global::GUTSchedule.Droid.Resource.Id.icon_group;
|
||||||
global::Xamarin.Essentials.Resource.Id.info = global::GUT.Schedule.Resource.Id.info;
|
global::Xamarin.Essentials.Resource.Id.info = global::GUTSchedule.Droid.Resource.Id.info;
|
||||||
global::Xamarin.Essentials.Resource.Id.italic = global::GUT.Schedule.Resource.Id.italic;
|
global::Xamarin.Essentials.Resource.Id.italic = global::GUTSchedule.Droid.Resource.Id.italic;
|
||||||
global::Xamarin.Essentials.Resource.Id.left = global::GUT.Schedule.Resource.Id.left;
|
global::Xamarin.Essentials.Resource.Id.left = global::GUTSchedule.Droid.Resource.Id.left;
|
||||||
global::Xamarin.Essentials.Resource.Id.line1 = global::GUT.Schedule.Resource.Id.line1;
|
global::Xamarin.Essentials.Resource.Id.line1 = global::GUTSchedule.Droid.Resource.Id.line1;
|
||||||
global::Xamarin.Essentials.Resource.Id.line3 = global::GUT.Schedule.Resource.Id.line3;
|
global::Xamarin.Essentials.Resource.Id.line3 = global::GUTSchedule.Droid.Resource.Id.line3;
|
||||||
global::Xamarin.Essentials.Resource.Id.none = global::GUT.Schedule.Resource.Id.none;
|
global::Xamarin.Essentials.Resource.Id.none = global::GUTSchedule.Droid.Resource.Id.none;
|
||||||
global::Xamarin.Essentials.Resource.Id.normal = global::GUT.Schedule.Resource.Id.normal;
|
global::Xamarin.Essentials.Resource.Id.normal = global::GUTSchedule.Droid.Resource.Id.normal;
|
||||||
global::Xamarin.Essentials.Resource.Id.notification_background = global::GUT.Schedule.Resource.Id.notification_background;
|
global::Xamarin.Essentials.Resource.Id.notification_background = global::GUTSchedule.Droid.Resource.Id.notification_background;
|
||||||
global::Xamarin.Essentials.Resource.Id.notification_main_column = global::GUT.Schedule.Resource.Id.notification_main_column;
|
global::Xamarin.Essentials.Resource.Id.notification_main_column = global::GUTSchedule.Droid.Resource.Id.notification_main_column;
|
||||||
global::Xamarin.Essentials.Resource.Id.notification_main_column_container = global::GUT.Schedule.Resource.Id.notification_main_column_container;
|
global::Xamarin.Essentials.Resource.Id.notification_main_column_container = global::GUTSchedule.Droid.Resource.Id.notification_main_column_container;
|
||||||
global::Xamarin.Essentials.Resource.Id.right = global::GUT.Schedule.Resource.Id.right;
|
global::Xamarin.Essentials.Resource.Id.right = global::GUTSchedule.Droid.Resource.Id.right;
|
||||||
global::Xamarin.Essentials.Resource.Id.right_icon = global::GUT.Schedule.Resource.Id.right_icon;
|
global::Xamarin.Essentials.Resource.Id.right_icon = global::GUTSchedule.Droid.Resource.Id.right_icon;
|
||||||
global::Xamarin.Essentials.Resource.Id.right_side = global::GUT.Schedule.Resource.Id.right_side;
|
global::Xamarin.Essentials.Resource.Id.right_side = global::GUTSchedule.Droid.Resource.Id.right_side;
|
||||||
global::Xamarin.Essentials.Resource.Id.start = global::GUT.Schedule.Resource.Id.start;
|
global::Xamarin.Essentials.Resource.Id.start = global::GUTSchedule.Droid.Resource.Id.start;
|
||||||
global::Xamarin.Essentials.Resource.Id.tag_transition_group = global::GUT.Schedule.Resource.Id.tag_transition_group;
|
global::Xamarin.Essentials.Resource.Id.tag_transition_group = global::GUTSchedule.Droid.Resource.Id.tag_transition_group;
|
||||||
global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_event_manager = global::GUT.Schedule.Resource.Id.tag_unhandled_key_event_manager;
|
global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_event_manager = global::GUTSchedule.Droid.Resource.Id.tag_unhandled_key_event_manager;
|
||||||
global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_listeners = global::GUT.Schedule.Resource.Id.tag_unhandled_key_listeners;
|
global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_listeners = global::GUTSchedule.Droid.Resource.Id.tag_unhandled_key_listeners;
|
||||||
global::Xamarin.Essentials.Resource.Id.text = global::GUT.Schedule.Resource.Id.text;
|
global::Xamarin.Essentials.Resource.Id.text = global::GUTSchedule.Droid.Resource.Id.text;
|
||||||
global::Xamarin.Essentials.Resource.Id.text2 = global::GUT.Schedule.Resource.Id.text2;
|
global::Xamarin.Essentials.Resource.Id.text2 = global::GUTSchedule.Droid.Resource.Id.text2;
|
||||||
global::Xamarin.Essentials.Resource.Id.time = global::GUT.Schedule.Resource.Id.time;
|
global::Xamarin.Essentials.Resource.Id.time = global::GUTSchedule.Droid.Resource.Id.time;
|
||||||
global::Xamarin.Essentials.Resource.Id.title = global::GUT.Schedule.Resource.Id.title;
|
global::Xamarin.Essentials.Resource.Id.title = global::GUTSchedule.Droid.Resource.Id.title;
|
||||||
global::Xamarin.Essentials.Resource.Id.top = global::GUT.Schedule.Resource.Id.top;
|
global::Xamarin.Essentials.Resource.Id.top = global::GUTSchedule.Droid.Resource.Id.top;
|
||||||
global::Xamarin.Essentials.Resource.Integer.status_bar_notification_info_maxnum = global::GUT.Schedule.Resource.Integer.status_bar_notification_info_maxnum;
|
global::Xamarin.Essentials.Resource.Integer.status_bar_notification_info_maxnum = global::GUTSchedule.Droid.Resource.Integer.status_bar_notification_info_maxnum;
|
||||||
global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_page = global::GUT.Schedule.Resource.Layout.browser_actions_context_menu_page;
|
global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_page = global::GUTSchedule.Droid.Resource.Layout.browser_actions_context_menu_page;
|
||||||
global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_row = global::GUT.Schedule.Resource.Layout.browser_actions_context_menu_row;
|
global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_row = global::GUTSchedule.Droid.Resource.Layout.browser_actions_context_menu_row;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_action = global::GUT.Schedule.Resource.Layout.notification_action;
|
global::Xamarin.Essentials.Resource.Layout.notification_action = global::GUTSchedule.Droid.Resource.Layout.notification_action;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_action_tombstone = global::GUT.Schedule.Resource.Layout.notification_action_tombstone;
|
global::Xamarin.Essentials.Resource.Layout.notification_action_tombstone = global::GUTSchedule.Droid.Resource.Layout.notification_action_tombstone;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_template_custom_big = global::GUT.Schedule.Resource.Layout.notification_template_custom_big;
|
global::Xamarin.Essentials.Resource.Layout.notification_template_custom_big = global::GUTSchedule.Droid.Resource.Layout.notification_template_custom_big;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_template_icon_group = global::GUT.Schedule.Resource.Layout.notification_template_icon_group;
|
global::Xamarin.Essentials.Resource.Layout.notification_template_icon_group = global::GUTSchedule.Droid.Resource.Layout.notification_template_icon_group;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_template_part_chronometer = global::GUT.Schedule.Resource.Layout.notification_template_part_chronometer;
|
global::Xamarin.Essentials.Resource.Layout.notification_template_part_chronometer = global::GUTSchedule.Droid.Resource.Layout.notification_template_part_chronometer;
|
||||||
global::Xamarin.Essentials.Resource.Layout.notification_template_part_time = global::GUT.Schedule.Resource.Layout.notification_template_part_time;
|
global::Xamarin.Essentials.Resource.Layout.notification_template_part_time = global::GUTSchedule.Droid.Resource.Layout.notification_template_part_time;
|
||||||
global::Xamarin.Essentials.Resource.String.status_bar_notification_info_overflow = global::GUT.Schedule.Resource.String.status_bar_notification_info_overflow;
|
global::Xamarin.Essentials.Resource.String.status_bar_notification_info_overflow = global::GUTSchedule.Droid.Resource.String.status_bar_notification_info_overflow;
|
||||||
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification = global::GUT.Schedule.Resource.Style.TextAppearance_Compat_Notification;
|
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification = global::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification;
|
||||||
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Info = global::GUT.Schedule.Resource.Style.TextAppearance_Compat_Notification_Info;
|
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Info = global::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Info;
|
||||||
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::GUT.Schedule.Resource.Style.TextAppearance_Compat_Notification_Line2;
|
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2;
|
||||||
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Time = global::GUT.Schedule.Resource.Style.TextAppearance_Compat_Notification_Time;
|
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Time = global::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Time;
|
||||||
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Title = global::GUT.Schedule.Resource.Style.TextAppearance_Compat_Notification_Title;
|
global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Title = global::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Title;
|
||||||
global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionContainer = global::GUT.Schedule.Resource.Style.Widget_Compat_NotificationActionContainer;
|
global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionContainer = global::GUTSchedule.Droid.Resource.Style.Widget_Compat_NotificationActionContainer;
|
||||||
global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionText = global::GUT.Schedule.Resource.Style.Widget_Compat_NotificationActionText;
|
global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionText = global::GUTSchedule.Droid.Resource.Style.Widget_Compat_NotificationActionText;
|
||||||
global::Xamarin.Essentials.Resource.Style.Widget_Support_CoordinatorLayout = global::GUT.Schedule.Resource.Style.Widget_Support_CoordinatorLayout;
|
global::Xamarin.Essentials.Resource.Style.Widget_Support_CoordinatorLayout = global::GUTSchedule.Droid.Resource.Style.Widget_Support_CoordinatorLayout;
|
||||||
global::Xamarin.Essentials.Resource.Xml.xamarin_essentials_fileprovider_file_paths = global::GUT.Schedule.Resource.Xml.xamarin_essentials_fileprovider_file_paths;
|
global::Xamarin.Essentials.Resource.Xml.xamarin_essentials_fileprovider_file_paths = global::GUTSchedule.Droid.Resource.Xml.xamarin_essentials_fileprovider_file_paths;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem = global::GUT.Schedule.Resource.Styleable.ColorStateListItem;
|
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem = global::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_alpha = global::GUT.Schedule.Resource.Styleable.ColorStateListItem_alpha;
|
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_alpha = global::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem_alpha;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_alpha = global::GUT.Schedule.Resource.Styleable.ColorStateListItem_android_alpha;
|
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_alpha = global::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem_android_alpha;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_color = global::GUT.Schedule.Resource.Styleable.ColorStateListItem_android_color;
|
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_color = global::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem_android_color;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_keylines = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_keylines;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_keylines = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_keylines;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_statusBarBackground;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline;
|
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily = global::GUT.Schedule.Resource.Styleable.FontFamily;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily = global::GUTSchedule.Droid.Resource.Styleable.FontFamily;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderAuthority = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderAuthority;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderAuthority = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderAuthority;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderCerts = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderCerts;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderCerts = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderCerts;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderFetchStrategy;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderFetchTimeout;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderPackage = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderPackage;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderPackage = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderPackage;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderQuery = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderQuery;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderQuery = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderQuery;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont = global::GUT.Schedule.Resource.Styleable.FontFamilyFont;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_font = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_android_font;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_font = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_font;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontStyle = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_android_fontStyle;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontStyle = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_android_fontVariationSettings;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontWeight = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_android_fontWeight;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontWeight = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_android_ttcIndex;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_font = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_font;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_font = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_font;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontStyle = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontStyle;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontStyle = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontStyle;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontVariationSettings;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontWeight = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontWeight;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontWeight = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontWeight;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_ttcIndex = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_ttcIndex;
|
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_ttcIndex = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_ttcIndex;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor = global::GUT.Schedule.Resource.Styleable.GradientColor;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor = global::GUTSchedule.Droid.Resource.Styleable.GradientColor;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerColor = global::GUT.Schedule.Resource.Styleable.GradientColor_android_centerColor;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerColor = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_centerColor;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerX = global::GUT.Schedule.Resource.Styleable.GradientColor_android_centerX;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerX = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_centerX;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerY = global::GUT.Schedule.Resource.Styleable.GradientColor_android_centerY;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerY = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_centerY;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endColor = global::GUT.Schedule.Resource.Styleable.GradientColor_android_endColor;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endColor = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_endColor;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endX = global::GUT.Schedule.Resource.Styleable.GradientColor_android_endX;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endX = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_endX;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endY = global::GUT.Schedule.Resource.Styleable.GradientColor_android_endY;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endY = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_endY;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_gradientRadius = global::GUT.Schedule.Resource.Styleable.GradientColor_android_gradientRadius;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_gradientRadius = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_gradientRadius;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startColor = global::GUT.Schedule.Resource.Styleable.GradientColor_android_startColor;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startColor = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_startColor;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startX = global::GUT.Schedule.Resource.Styleable.GradientColor_android_startX;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startX = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_startX;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startY = global::GUT.Schedule.Resource.Styleable.GradientColor_android_startY;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startY = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_startY;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_tileMode = global::GUT.Schedule.Resource.Styleable.GradientColor_android_tileMode;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_tileMode = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_tileMode;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_type = global::GUT.Schedule.Resource.Styleable.GradientColor_android_type;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_type = global::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_type;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem = global::GUT.Schedule.Resource.Styleable.GradientColorItem;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem = global::GUTSchedule.Droid.Resource.Styleable.GradientColorItem;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_color = global::GUT.Schedule.Resource.Styleable.GradientColorItem_android_color;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_color = global::GUTSchedule.Droid.Resource.Styleable.GradientColorItem_android_color;
|
||||||
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_offset = global::GUT.Schedule.Resource.Styleable.GradientColorItem_android_offset;
|
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_offset = global::GUTSchedule.Droid.Resource.Styleable.GradientColorItem_android_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Animation
|
public partial class Animation
|
||||||
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GUTSchedule
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns <see cref="DateTime"/> instance based on study week number, weekday and semester start day number
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="week">Number of the study week</param>
|
||||||
|
/// <param name="weekday">Weekday</param>
|
||||||
|
/// <returns><see cref="DateTime"/> instance based on study week number, weekday and semester start day number</returns>
|
||||||
|
public static DateTime GetDateFromWeeks(int week, int weekday)
|
||||||
|
{
|
||||||
|
DateTime dt = new DateTime(DateTime.Today.Year, DateTime.Today.Month >= 8 ? 9 : 2, Data.FirstWeekDay);
|
||||||
|
|
||||||
|
dt = dt.AddDays(--week * 7);
|
||||||
|
dt = dt.AddDays(--weekday);
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetContent(this HttpRequestMessage request, params (string key, string value)[] values)
|
||||||
|
{
|
||||||
|
if (request == null)
|
||||||
|
throw new ArgumentNullException(nameof(request));
|
||||||
|
|
||||||
|
Dictionary<string, string> body = new Dictionary<string, string>();
|
||||||
|
foreach ((string key, string value) in values)
|
||||||
|
body.Add(key, value);
|
||||||
|
request.Content = new FormUrlEncodedContent(body);
|
||||||
|
}
|
||||||
|
public static async Task<string> GetString(this HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
if (response == null)
|
||||||
|
throw new ArgumentNullException(nameof(response));
|
||||||
|
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
return Encoding.GetEncoding("Windows-1251").GetString(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.4</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AngleSharp" Version="0.13.0" />
|
||||||
|
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Models
|
||||||
|
{
|
||||||
|
public class CabinetSubject
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Cabinet { get; set; }
|
||||||
|
public string Order { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public DateTime EndTime { get; set; }
|
||||||
|
public string Opponent { get; set; }
|
||||||
|
public bool ProfessorSchedule { get; set; }
|
||||||
|
|
||||||
|
public CabinetSubject(string name, string type, string cabinet, string opponent, int year, int month, int day, string schedule, bool profSchedule)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
Cabinet = cabinet;
|
||||||
|
Opponent = opponent;
|
||||||
|
ProfessorSchedule = profSchedule;
|
||||||
|
|
||||||
|
string[] time = schedule.Split('-');
|
||||||
|
|
||||||
|
StartTime = new DateTime(year, month, day, int.Parse(time[0].Split('.')[0]), int.Parse(time[0].Split('.')[1]), 0);
|
||||||
|
EndTime = new DateTime(year, month, day, int.Parse(time[1].Split('.')[0]), int.Parse(time[1].Split('.')[1]), 0);
|
||||||
|
switch (time[0])
|
||||||
|
{
|
||||||
|
case "09.00": Order = "1"; break;
|
||||||
|
case "10.45": Order = "2"; break;
|
||||||
|
case "13.00": Order = "3"; break;
|
||||||
|
case "14.45": Order = "4"; break;
|
||||||
|
case "16.30": Order = "5"; break;
|
||||||
|
case "18.15": Order = "6"; break;
|
||||||
|
case "20.00": Order = "7"; break;
|
||||||
|
case "10.30": Order = "2"; break; //Расписание для пар по физ-ре
|
||||||
|
case "12.00": Order = "3"; break;
|
||||||
|
case "13.30": Order = "4"; break;
|
||||||
|
case "15.00": Order = "5"; break;
|
||||||
|
case "18.00": Order = "7"; break;
|
||||||
|
default: Order = ""; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using GUTSchedule.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GUTSchedule
|
||||||
|
{
|
||||||
|
public static class Data
|
||||||
|
{
|
||||||
|
public static List<(string Id, string Name)> Faculties { get; set; }
|
||||||
|
public static List<(string Id, string Name)> Groups { get; set; }
|
||||||
|
public static int FirstWeekDay { get; set; }
|
||||||
|
public static DateTime StartDate { get; set; } = DateTime.Today;
|
||||||
|
public static DateTime EndDate { get; set; } = DateTime.Today.AddDays(7);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Export parameters
|
||||||
|
/// </summary>
|
||||||
|
public static DataSet DataSet { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Models
|
||||||
|
{
|
||||||
|
public class DataSet
|
||||||
|
{
|
||||||
|
public string Calendar { get; set; }
|
||||||
|
public string Faculty { get; set; }
|
||||||
|
public int Course { get; set; }
|
||||||
|
public string Group { get; set; }
|
||||||
|
public int Reminder { get; set; }
|
||||||
|
public bool AddGroupToTitle { get; set; }
|
||||||
|
public HttpClient HttpClient { get; set; }
|
||||||
|
public bool? IsProfessor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GUTSchedule.Models
|
||||||
|
{
|
||||||
|
public class Subject
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Professor { get; set; }
|
||||||
|
public string[] Cabinets { get; set; }
|
||||||
|
public string Order { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public DateTime EndTime { get; set; }
|
||||||
|
public string Group { get; set; }
|
||||||
|
|
||||||
|
public static List<Subject> GetSubject(string name, string type, string professor, string place, int order, string[] weeks, int weekday, string group)
|
||||||
|
{
|
||||||
|
List<Subject> subjects = new List<Subject>();
|
||||||
|
string[] cabinets = place.Replace("ауд.: ", "").Replace("; Б22", "").Split(';');
|
||||||
|
string pair = order < 10 ? order.ToString() : $"Ф{order - 81}";
|
||||||
|
|
||||||
|
foreach (string week in weeks)
|
||||||
|
subjects.Add(new Subject(name, type, professor, cabinets, pair, int.Parse(week), weekday, group));
|
||||||
|
|
||||||
|
return subjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subject(string name, string type, string prof, string[] cabs, string order, int week, int weekday, string group)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
Professor = prof;
|
||||||
|
Cabinets = cabs;
|
||||||
|
Order = order;
|
||||||
|
Group = group;
|
||||||
|
|
||||||
|
StartTime = Extensions.GetDateFromWeeks(week, weekday);
|
||||||
|
string rawTime;
|
||||||
|
switch (order)
|
||||||
|
{
|
||||||
|
case "1": rawTime = "9:00"; break;
|
||||||
|
case "2": rawTime = "10:45"; break;
|
||||||
|
case "3": rawTime = "13:00"; break;
|
||||||
|
case "4": rawTime = "14:45"; break;
|
||||||
|
case "5": rawTime = "16:30"; break;
|
||||||
|
case "6": rawTime = "18:15"; break;
|
||||||
|
case "7": rawTime = "20:00"; break;
|
||||||
|
case "Ф1": rawTime = "9:00"; break; //Расписание для пар по физ-ре
|
||||||
|
case "Ф2": rawTime = "10:30"; break;
|
||||||
|
case "Ф3": rawTime = "12:00"; break;
|
||||||
|
case "Ф4": rawTime = "13:30"; break;
|
||||||
|
case "Ф5": rawTime = "15:00"; break;
|
||||||
|
case "Ф6": rawTime = "16:30"; break;
|
||||||
|
case "Ф7": rawTime = "18:00"; break;
|
||||||
|
default: rawTime = "9:00"; break;
|
||||||
|
}
|
||||||
|
StartTime = StartTime.Add(TimeSpan.Parse(rawTime));
|
||||||
|
EndTime = StartTime + TimeSpan.FromMinutes(order.Contains("Ф") ? 90 : 95);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
using AngleSharp.Dom;
|
||||||
|
using AngleSharp.Html.Dom;
|
||||||
|
using AngleSharp.Html.Parser;
|
||||||
|
using GUTSchedule.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GUTSchedule
|
||||||
|
{
|
||||||
|
public static class Parser
|
||||||
|
{
|
||||||
|
public static async Task<List<Subject>> LoadSchedule()
|
||||||
|
{
|
||||||
|
List<Subject> schedule = new List<Subject>();
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "group_el", "0" },
|
||||||
|
{ "kurs", Data.DataSet.Course.ToString() },
|
||||||
|
{ "type_z", "1" },
|
||||||
|
{ "faculty", Data.DataSet.Faculty },
|
||||||
|
{ "group", Data.DataSet.Group },
|
||||||
|
{ "ok", "Показать" },
|
||||||
|
{ "schet", GetCurrentSemester() }
|
||||||
|
};
|
||||||
|
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new")
|
||||||
|
{
|
||||||
|
Content = new FormUrlEncodedContent(requestBody)
|
||||||
|
};
|
||||||
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request);
|
||||||
|
|
||||||
|
IHtmlDocument doc = new HtmlParser().ParseDocument(await response.Content.ReadAsStringAsync());
|
||||||
|
|
||||||
|
string groupName = Data.Groups.First(i => i.Id == Data.DataSet.Group).Name;
|
||||||
|
|
||||||
|
IHtmlCollection<IElement> pairs = doc.QuerySelectorAll(".pair");
|
||||||
|
foreach (IElement item in pairs)
|
||||||
|
{
|
||||||
|
string name, type, professor, place;
|
||||||
|
int order, weekday;
|
||||||
|
string[] weeks;
|
||||||
|
|
||||||
|
name = item.QuerySelector(".subect strong")?.TextContent ?? "Неизвестный предмет (см. Расписание)";
|
||||||
|
type = item.QuerySelector(".type").TextContent.Replace("(", "").Replace(")", "");
|
||||||
|
professor = item.QuerySelector(".teacher")?.GetAttribute("title").Replace(";", "") ?? "";
|
||||||
|
place = item.QuerySelector(".aud")?.TextContent ?? "СПбГУТ";
|
||||||
|
order = int.Parse(item.GetAttribute("pair")) - 1;
|
||||||
|
weeks = item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Replace(" ", "").Split(',');
|
||||||
|
weekday = int.Parse(item.GetAttribute("weekday"));
|
||||||
|
|
||||||
|
schedule.AddRange(Subject.GetSubject(name, type, professor, place, order, weeks, weekday, groupName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task LoadFaculties()
|
||||||
|
{
|
||||||
|
Data.Faculties = new List<(string, string)>();
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "choice", "1" },
|
||||||
|
{ "kurs", "0" },
|
||||||
|
{ "type_z", "1" },
|
||||||
|
{ "schet", GetCurrentSemester() }
|
||||||
|
};
|
||||||
|
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||||
|
{
|
||||||
|
Content = new FormUrlEncodedContent(requestBody)
|
||||||
|
};
|
||||||
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request);
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
if (string.IsNullOrWhiteSpace(responseBody))
|
||||||
|
throw new NullReferenceException("Расписание на текущий семестр еще не объявлено");
|
||||||
|
|
||||||
|
foreach (string s in responseBody.Split(';'))
|
||||||
|
try { Data.Faculties.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task LoadGroups(string facultyId, int course)
|
||||||
|
{
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "choice", "1" },
|
||||||
|
{ "kurs", course.ToString() },
|
||||||
|
{ "type_z", "1" },
|
||||||
|
{ "faculty", facultyId },
|
||||||
|
{ "schet", GetCurrentSemester() }
|
||||||
|
};
|
||||||
|
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||||
|
{
|
||||||
|
Content = new FormUrlEncodedContent(requestBody)
|
||||||
|
};
|
||||||
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request);
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
Data.Groups = new List<(string, string)>();
|
||||||
|
foreach (string s in responseBody.Split(';'))
|
||||||
|
try { Data.Groups.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetCurrentSemester()
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Today;
|
||||||
|
|
||||||
|
if (now.Month > 8)
|
||||||
|
return $"205.{now.Year - 2000}{now.Year - 1999}/1";
|
||||||
|
else
|
||||||
|
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<List<CabinetSubject>> GetCabinetSchedule(HttpClient client, DateTime date, bool checkProfSchedule)
|
||||||
|
{
|
||||||
|
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"https://cabs.itut.ru/cabinet/project/cabinet/forms/{(checkProfSchedule ? "pr_" : "")}raspisanie_kalendar.php");
|
||||||
|
request.SetContent(
|
||||||
|
("month", date.Month.ToString()),
|
||||||
|
("year", date.Year.ToString()),
|
||||||
|
("type_z", "0"));
|
||||||
|
|
||||||
|
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
|
||||||
|
string responseContent = await response.GetString().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
throw new HttpRequestException(responseContent);
|
||||||
|
|
||||||
|
IHtmlDocument doc = new HtmlParser().ParseDocument(responseContent);
|
||||||
|
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
||||||
|
|
||||||
|
if (!checkProfSchedule)
|
||||||
|
Data.DataSet.Group = doc.QuerySelector(".style_gr b").TextContent;
|
||||||
|
|
||||||
|
foreach (var i in doc.QuerySelectorAll("td").Where(i => i.GetAttribute("style") == "text-align: center; vertical-align: top"))
|
||||||
|
for (int k = 0; k < i.QuerySelectorAll("i").Length; k++)
|
||||||
|
{
|
||||||
|
CabinetSubject item = new CabinetSubject(
|
||||||
|
name: i.QuerySelectorAll("b")[k * 2 + 1].TextContent,
|
||||||
|
type: i.QuerySelectorAll("i")[k].TextContent,
|
||||||
|
cabinet: i.QuerySelectorAll("small")[k].NextSibling.TextContent.Replace("; Б22", ""),
|
||||||
|
opponent: i.QuerySelectorAll("i")[k].NextSibling.NextSibling.NodeType == NodeType.Text ?
|
||||||
|
i.QuerySelectorAll("i")[k].NextSibling.NextSibling.TextContent : "",
|
||||||
|
year: date.Year,
|
||||||
|
month: date.Month,
|
||||||
|
day: int.Parse(i.ChildNodes[0].TextContent),
|
||||||
|
schedule: i.QuerySelectorAll("b")[k * 2 + 2].TextContent,
|
||||||
|
checkProfSchedule);
|
||||||
|
schedule.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge duplicating entries
|
||||||
|
schedule.OrderByDescending(i => i.StartTime);
|
||||||
|
for (int k = 1; k < schedule.Count; k++)
|
||||||
|
if (schedule[k - 1].StartTime == schedule[k].StartTime &&
|
||||||
|
schedule[k - 1].Name == schedule[k].Name &&
|
||||||
|
schedule[k - 1].Type == schedule[k].Type)
|
||||||
|
{
|
||||||
|
schedule[k - 1].Opponent += "\n" + schedule[k].Opponent;
|
||||||
|
schedule[k - 1].Cabinet += "; " + schedule[k].Cabinet;
|
||||||
|
schedule.RemoveAt(k--);
|
||||||
|
}
|
||||||
|
|
||||||
|
return schedule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||