1
0
mirror of https://github.com/XFox111/GUTSchedule.git synced 2026-04-22 06:58:01 +03:00

Splitted and added UWP project

This commit is contained in:
Michael Gordeev
2020-02-10 17:43:20 +03:00
parent 882b7c571d
commit 534f2e2966
73 changed files with 1992 additions and 1440 deletions
+7
View File
@@ -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>
+90
View File
@@ -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();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

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)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,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>
+124 -1
View File
@@ -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
}
}
-154
View File
@@ -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();
}
}
}
-71
View File
@@ -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",
_ => ""
};
}
}
}
-20
View File
@@ -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);
}
}
}
-178
View File
@@ -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
}
}
+154
View File
@@ -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: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 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: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

+46
View File
@@ -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;
}
}
}
}
+20
View File
@@ -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);
}
}
}
+177
View File
@@ -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;
}
}
}