Merge pull request #20 from XFox111/uwp-version
[14-Mar-2020] Major project update
@@ -25,9 +25,10 @@ If applicable, add screenshots to help explain your problem.
|
||||
|
||||
### Environment
|
||||
Please complete the following information:
|
||||
- Device: [e.g. Google Pixel 3 XL]
|
||||
- Android OS version: [e.g. 7.1]
|
||||
- Application version: [e.g. 1.0.1]
|
||||
- Platform: [e.g. Windows 10 Pro]
|
||||
- Device: [e.g. Microsoft Surface Pro 6]
|
||||
- OS version: [e.g. 1909 (10.0.18363)]
|
||||
- Application version: [e.g. 20200202.1]
|
||||
|
||||
### Additional context
|
||||
Add any other context about the problem here.
|
||||
@@ -87,13 +87,26 @@ If you are interested in writing code to fix issues or implement new awesome fea
|
||||
git clone https://github.com/xfox111/GUTSchedule.git
|
||||
```
|
||||
2. Open `GUT.Schedule/GUT.Schedule.sln` using [Microsoft Visual Studio](https://visualstudio.microsoft.com/) 2019 or later
|
||||
- Make sure you have properly installed and congigured [Xamarin.Android](https://docs.microsoft.com/en-us/xamarin/android/get-started/installation/) environment
|
||||
3. On the VS toolbar choose build configuration:
|
||||
- Make sure you have properly installed and congigured [Xamarin.Android](https://docs.microsoft.com/en-us/xamarin/android/get-started/installation/) and UWP development environments
|
||||
|
||||
**Android**
|
||||
|
||||
1. In `Solution Explorer` right-click `GUTSchedule.Droid` project and click `Set as StartUp Project`
|
||||
2. On the VS toolbar choose build configuration:
|
||||
- `Debug` for building and deploying test version of the app
|
||||
- `Release` for building final version of application and creating AppBundle package (.aab)
|
||||
- `Release (APK)` for building final version of application and creating Android package fike (.apk)
|
||||
4. To ensure that code compiles go to `Build -> Build Solution`
|
||||
5. [Debug application](https://docs.microsoft.com/en-us/xamarin/android/deploy-test/debugging/) on an actual device or Android Emulator
|
||||
3. To ensure that code compiles go to `Build -> Build Solution`
|
||||
4. [Debug application](https://docs.microsoft.com/en-us/xamarin/android/deploy-test/debugging/) on an actual device or Android Emulator
|
||||
|
||||
**UWP**
|
||||
|
||||
1. In `Solution Explorer` right-click `GUTSchedule.UWP (Universal Windows)` project and click `Set as StartUp Project`
|
||||
2. On the VS toolbar choose build configuration:
|
||||
- `Debug` for building and deploying test version of the app
|
||||
- `Release` for building final version of application and creating Appx packages
|
||||
3. To ensure that code compiles go to `Build -> Build Solution`
|
||||
4. [Debug application](https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/deploying-and-debugging-uwp-apps) on your machine or Windows Device Emulator
|
||||
|
||||
### Development workflow
|
||||
This section represents how contributors should interact with codebase implementing features and fixing bugs
|
||||
@@ -241,19 +254,30 @@ To avoid multiple pull requests resolving the same issue, let others know you ar
|
||||
### Contributing to translations
|
||||
If you want to help us to translate this application into other languages you can do it making these steps:
|
||||
|
||||
1. Navigate to `GUT.Schedule/GUT.Schedule/Resources`
|
||||
**Android**
|
||||
|
||||
1. Navigate to `GUT.Schedule/GUTSchedule.Droid/Resources`
|
||||
2. Create new folder named `values-lc` where `lc` is locale language.
|
||||
Folder name examples:
|
||||
- `values-uk` for Ukrainian
|
||||
- `values-be` for Belarusian
|
||||
- `values-ru` for Russian
|
||||
|
||||
> **Note** that we only accept region neutral localizations (e.g. pull request with `values-en-rUS` (English (United States)) folder will be rejected whether PR with `values-en` (English (Invarian Country)) folder will be accepted).
|
||||
For reference, here is a [list of Java locales](https://www.oracle.com/technetwork/java/javase/locales-137662.html) and [Android-supported locales via StackOverflow](https://stackoverflow.com/questions/7973023/what-is-the-list-of-supported-languages-locales-on-android).
|
||||
3. In the folder copy `strings.xml` file from `GUT.Schedule/GUT.Schedule/Resources/values`
|
||||
|
||||
3. In the folder copy `strings.xml` file from `GUT.Schedule/GUTSchedule.Droid/Resources/values`
|
||||
|
||||
**UWP**
|
||||
|
||||
1. Navigate to `GUT.Schedule/GUTSchedule.UWP/Strings`
|
||||
2. Clone the folder you want to base your localization on and change its name to match desired localization language. See [Globalization and localization](https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/globalizing-portal) for more information
|
||||
3. Open `.resw` files from the folder in Visual Studio or other text editor
|
||||
***
|
||||
4. Edit localization strings
|
||||
5. Commit changes and create a pull request
|
||||
|
||||
> **Note** that we only accept region neutral localizations (e.g. pull request with `values-en-rUS` (English (United States)) folder will be rejected whether PR with `values-en` (English) folder will be accepted).
|
||||
|
||||
### Submitting pull requests
|
||||
To enable us to quickly review and accept your pull requests, always create one pull request per issue and [link the issue in the pull request](https://github.com/blog/957-introducing-issue-mentions). Never merge multiple requests in one unless they have the same root cause. Be sure to follow our [Coding Guidelines](#coding-guidelines) and keep code changes as small as possible. Avoid pure formatting changes to code that has not been modified otherwise. Pull requests should contain tests whenever possible. Fill pull request content according to its template. Deviations from template are not recommended
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29609.76
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUT.Schedule", "GUT.Schedule\GUT.Schedule.csproj", "{A0471165-37F5-4309-8A92-42F1A6589EEE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release (APK)|Any CPU = Release (APK)|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{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.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.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|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.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {456DD1C4-9BC4-4D79-A999-8F85492E7C20}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,86 +0,0 @@
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Support.V4.Text;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Text.Method;
|
||||
using Android.Widget;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUT.Schedule.Activities
|
||||
{
|
||||
[Activity(Label = "@string/aboutTitle")]
|
||||
public class AboutActivity : AppCompatActivity
|
||||
{
|
||||
protected override async void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
(string name, string handle, string link)[] contacts = new (string, string, string)[]
|
||||
{
|
||||
(Resources.GetText(Resource.String.websiteContact), "https://xfox111.net", "https://xfox111.net"),
|
||||
(Resources.GetText(Resource.String.twitterContact), "@xfox111", "https://twitter.com/xfox111"),
|
||||
(Resources.GetText(Resource.String.vkontakteContact), "@xfox.mike", "https://vk.com/xfox.mike"),
|
||||
("LinkedIn", "@xfox", "https://linkedin.com/in/xfox"),
|
||||
("GitHub", "@xfox111", "https://github.com/xfox111"),
|
||||
};
|
||||
(string name, string link)[] links = new (string, string)[]
|
||||
{
|
||||
(Resources.GetText(Resource.String.privacyPolicyLink), "https://xfox111.net/Projects/GUTSchedule/PrivacyPolicy.txt"),
|
||||
("General Public License v3", "https://www.gnu.org/licenses/gpl-3.0"),
|
||||
(Resources.GetText(Resource.String.repositoryLink), "https://github.com/xfox111/gutschedule"),
|
||||
(Resources.GetText(Resource.String.notsLink), "http://tios.spbgut.ru/index.php"),
|
||||
(Resources.GetText(Resource.String.sutLink), "https://sut.ru"),
|
||||
};
|
||||
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.About);
|
||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||
|
||||
FindViewById<Button>(Resource.Id.feedback).Click += (s, e) =>
|
||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
||||
|
||||
FindViewById<TextView>(Resource.Id.contacts).SetText(
|
||||
HtmlCompat.FromHtml(string.Join("<br />", contacts.Select(i => $"<span>{i.name}:</span> <a href=\"{i.link}\">{i.handle}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.contacts).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.links).SetText(
|
||||
HtmlCompat.FromHtml(string.Join("<br />", links.Select(i => $"<a href=\"{i.link}\">{i.name}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.links).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
List<string> contributors = new List<string>();
|
||||
try
|
||||
{
|
||||
using HttpClient client = new HttpClient();
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/xfox111/gutschedule/contributors");
|
||||
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string resposeContent = await response.Content.ReadAsStringAsync();
|
||||
dynamic parsedResponse = JsonConvert.DeserializeObject(resposeContent);
|
||||
|
||||
foreach (var i in parsedResponse)
|
||||
if (i.type == "User" && ((string)i.login).ToLower() != "xfox111")
|
||||
contributors.Add((string)i.login);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (contributors.Count > 0)
|
||||
{
|
||||
FindViewById<TextView>(Resource.Id.contributors).SetText(
|
||||
HtmlCompat.FromHtml(string.Join(", ", contributors.Select(i => $"<a href=\"https://github.com/{i}\">@{i}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.contributors).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.contributorsTitle).Visibility = Android.Views.ViewStates.Visible;
|
||||
FindViewById<TextView>(Resource.Id.contributors).Visibility = Android.Views.ViewStates.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
using GUT.Schedule.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUT.Schedule.Activities
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows status of schedule export process
|
||||
/// </summary>
|
||||
[Activity(Theme = "@style/AppTheme.Light.SplashScreen")]
|
||||
public class ExportActivity : Activity
|
||||
{
|
||||
TextView status;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.Export);
|
||||
|
||||
status = FindViewById<TextView>(Resource.Id.status);
|
||||
|
||||
Export();
|
||||
}
|
||||
|
||||
private async void Export()
|
||||
{
|
||||
try
|
||||
{
|
||||
if(Data.DataSet.IsProfessor == true)
|
||||
status.Text = Resources.GetText(Resource.String.potatoLoadingStatus); // For some reason professors' schedule loads much slower
|
||||
else
|
||||
status.Text = Resources.GetText(Resource.String.loadingStatus);
|
||||
|
||||
if (Data.DataSet.HttpClient != null)
|
||||
{
|
||||
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
||||
|
||||
for(DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
||||
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, false)); // Even though the user can be professor he can be also PhD student (and have his student schedule)
|
||||
|
||||
if(Data.DataSet.IsProfessor == true)
|
||||
for (DateTime d = Data.StartDate; d <= Data.EndDate; d = d.AddMonths(1))
|
||||
schedule.AddRange(await Parser.GetCabinetSchedule(Data.DataSet.HttpClient, d, true));
|
||||
|
||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
||||
Calendar.Export(schedule);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Subject> schedule = await Parser.LoadSchedule();
|
||||
|
||||
schedule = schedule.FindAll(i => i.StartTime.Date >= Data.StartDate && i.StartTime.Date <= Data.EndDate); // Filtering schedule according to export range
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.calendarExportStatus);
|
||||
Calendar.Export(schedule);
|
||||
}
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.doneStatus);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(Resources.GetText(Resource.String.connectionFailMessage))
|
||||
.SetTitle(e.Message)
|
||||
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed())
|
||||
.SetNegativeButton(Resources.GetText(Resource.String.repeat), (s, e) => Export());
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(e.Message)
|
||||
.SetTitle(e.GetType().ToString())
|
||||
.SetPositiveButton("ОК", (s, e) => base.OnBackPressed());
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
return;
|
||||
}
|
||||
base.OnBackPressed(); // Navigates back to main activity (always because I don't allow backward navigation)
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { } // Disables back button
|
||||
}
|
||||
}
|
||||
@@ -1,353 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Support.V4.Text;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Text.Method;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using AngleSharp.Html.Dom;
|
||||
using AngleSharp.Html.Parser;
|
||||
using GUT.Schedule.Models;
|
||||
|
||||
namespace GUT.Schedule.Activities
|
||||
{
|
||||
[Activity]
|
||||
public class MainActivity : AppCompatActivity
|
||||
{
|
||||
Button start, end, export;
|
||||
Button forDay, forWeek, forMonth, forSemester;
|
||||
Spinner faculty, course, group, reminder, calendar;
|
||||
CheckBox groupTitle, authorize;
|
||||
TextView error;
|
||||
LinearLayout studentParams, profParams;
|
||||
EditText email, password;
|
||||
|
||||
ISharedPreferences prefs;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.Main);
|
||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||
|
||||
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||
|
||||
AssignVariables();
|
||||
|
||||
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
||||
int s = Data.Faculties.FindIndex(i => i.Id == prefs.GetString("Faculty", "-123"));
|
||||
faculty.SetSelection(s == -1 ? 0 : s);
|
||||
|
||||
course.SetList(this, "1234".ToCharArray());
|
||||
course.SetSelection(prefs.GetInt("Course", 0)); // IDK why but this shit triggers events anyway (even if they are set in the next line. It seem to be that there's some asynchronous shit somewhere there)
|
||||
// P.S. Fuck Android
|
||||
|
||||
AddEvents();
|
||||
|
||||
// Settings spinners' dropdown lists content
|
||||
reminder.SetList(this, new[]
|
||||
{
|
||||
Resources.GetText(Resource.String.noReminderOption),
|
||||
Resources.GetText(Resource.String.inTimeReminderOption),
|
||||
Resources.GetText(Resource.String.fiveMinuteReminderOption),
|
||||
Resources.GetText(Resource.String.tenMinuteReminderOption)
|
||||
});
|
||||
reminder.SetSelection(prefs.GetInt("Reminder", 0));
|
||||
|
||||
calendar.SetList(this, Calendar.Calendars.Select(i => i.Name));
|
||||
s = Calendar.Calendars.FindIndex(i => i.Id == prefs.GetString("Calendar", "-123"));
|
||||
calendar.SetSelection(s == -1 ? 0 : s);
|
||||
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
|
||||
groupTitle.Checked = prefs.GetBoolean("AddGroupToHeader", false);
|
||||
authorize.Checked = prefs.GetBoolean("Authorize", true);
|
||||
|
||||
email.Text = prefs.GetString("email", "");
|
||||
password.Text = prefs.GetString("password", "");
|
||||
}
|
||||
|
||||
private async void Export_Click(object sender, EventArgs e)
|
||||
{
|
||||
error.Visibility = ViewStates.Gone;
|
||||
|
||||
if (Data.StartDate > Data.EndDate)
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.invalidDateRangeError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
HttpClient client = null;
|
||||
bool? isProf = null;
|
||||
if(authorize.Checked)
|
||||
{
|
||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.authorizationState), ToastLength.Short).Show();
|
||||
if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text))
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.invalidAuthorizationError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
export.Enabled = false;
|
||||
client = new HttpClient();
|
||||
|
||||
await client.GetAsync("https://cabs.itut.ru/cabinet/");
|
||||
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php");
|
||||
request.SetContent(
|
||||
("users", email.Text),
|
||||
("parole", password.Text));
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseContent = await response.GetString();
|
||||
export.Enabled = true;
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
error.Text = $"{Resources.GetText(Resource.String.authorizationError)}: {response.StatusCode}: {responseContent}";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
error.Text = $"{Resources.GetText(Resource.String.invalidCredentialError)} ({string.Join("; ", responseContent.Replace("error=", "", StringComparison.OrdinalIgnoreCase).Split('|'))})";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
export.Enabled = false;
|
||||
HttpResponseMessage verificationResponse = await client.GetAsync("https://cabs.itut.ru/cabinet/?login=yes");
|
||||
export.Enabled = true;
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await verificationResponse.GetString());
|
||||
if (doc.QuerySelectorAll("option").Any(i => i.TextContent.Contains("Сотрудник")))
|
||||
isProf = true;
|
||||
else
|
||||
isProf = false;
|
||||
|
||||
Data.Groups = null;
|
||||
|
||||
// Если ты это читаешь и у тебя возникли вопросы по типу "А какого хуя творится в коде ниже?!", то во-первых:
|
||||
// According to this SO thread: https://stackoverflow.com/questions/1925486/android-storing-username-and-password
|
||||
// I consider Preferences as safe enough method for storing credentials
|
||||
// А во-вторых, даже такой казалось бы небезопасный метод хранения учетных данных в сто раз надежнее того дерьма,
|
||||
// что творится на серверах Бонча (я не шучу, там все ОЧЕНЬ плохо)
|
||||
// Ну и в-третьих: Андроид - это пиздец и настоящий ад разработчика. И если бы была моя воля, я бы под него никогда не писал #FuckAndroid
|
||||
// З.Ы. Помнишь про второй пункт? Так вот, если ты используешь такой же пароль как в ЛК где-то еще, настоятельно рекомендую его поменять
|
||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("email", email.Text).Apply();
|
||||
PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("password", password.Text).Apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Data.Groups.Count < 1)
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.groupSelectionError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Forming export parameters
|
||||
Data.DataSet = new DataSet
|
||||
{
|
||||
Faculty = Data.Faculties[faculty.SelectedItemPosition].Id,
|
||||
Group = Data.Groups?[group.SelectedItemPosition].Id,
|
||||
Course = course.SelectedItemPosition + 1,
|
||||
AddGroupToTitle = groupTitle.Checked,
|
||||
Calendar = Calendar.Calendars[calendar.SelectedItemPosition].Id,
|
||||
Reminder = (reminder.SelectedItemPosition - 1) * 5,
|
||||
HttpClient = client,
|
||||
IsProfessor = isProf
|
||||
};
|
||||
|
||||
StartActivity(new Intent(this, typeof(ExportActivity)));
|
||||
}
|
||||
|
||||
private async void End_Click(object sender, EventArgs e)
|
||||
{
|
||||
Data.EndDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.EndDate);
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void Start_Click(object sender, EventArgs e)
|
||||
{
|
||||
Data.StartDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.StartDate);
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void UpdateGroupsList()
|
||||
{
|
||||
if (course.SelectedItem == null)
|
||||
return;
|
||||
|
||||
await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1);
|
||||
group.SetList(this, Data.Groups.Select(i => i.Name));
|
||||
|
||||
int s = Data.Groups?.FindIndex(i => i.Id == prefs.GetString("Group", "-123")) ?? 0;
|
||||
group.SetSelection(s == -1 ? 0 : s);
|
||||
}
|
||||
|
||||
private void SetDate(int days)
|
||||
{
|
||||
Data.EndDate = Data.StartDate.AddDays(days);
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
}
|
||||
|
||||
#region Init stuff
|
||||
private void AssignVariables()
|
||||
{
|
||||
start = FindViewById<Button>(Resource.Id.start);
|
||||
end = FindViewById<Button>(Resource.Id.end);
|
||||
export = FindViewById<Button>(Resource.Id.export);
|
||||
|
||||
forDay = FindViewById<Button>(Resource.Id.forDay);
|
||||
forWeek = FindViewById<Button>(Resource.Id.forWeek);
|
||||
forMonth = FindViewById<Button>(Resource.Id.forMonth);
|
||||
forSemester = FindViewById<Button>(Resource.Id.forSemester);
|
||||
|
||||
faculty = FindViewById<Spinner>(Resource.Id.faculty);
|
||||
course = FindViewById<Spinner>(Resource.Id.course);
|
||||
group = FindViewById<Spinner>(Resource.Id.group);
|
||||
reminder = FindViewById<Spinner>(Resource.Id.reminder);
|
||||
calendar = FindViewById<Spinner>(Resource.Id.calendar);
|
||||
|
||||
error = FindViewById<TextView>(Resource.Id.error);
|
||||
|
||||
groupTitle = FindViewById<CheckBox>(Resource.Id.groupTitle);
|
||||
authorize = FindViewById<CheckBox>(Resource.Id.authorization);
|
||||
|
||||
studentParams = FindViewById<LinearLayout>(Resource.Id.studentParams);
|
||||
profParams = FindViewById<LinearLayout>(Resource.Id.professorParams);
|
||||
|
||||
email = FindViewById<EditText>(Resource.Id.email);
|
||||
password = FindViewById<EditText>(Resource.Id.password);
|
||||
}
|
||||
|
||||
private void AddEvents()
|
||||
{
|
||||
faculty.ItemSelected += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutString("Faculty", Data.Faculties[e.Position].Id).Apply();
|
||||
UpdateGroupsList();
|
||||
};
|
||||
course.ItemSelected += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutInt("Course", e.Position).Apply();
|
||||
UpdateGroupsList();
|
||||
};
|
||||
authorize.CheckedChange += (s, e) =>
|
||||
{
|
||||
prefs.Edit().PutBoolean("Authorize", e.IsChecked).Apply();
|
||||
if (e.IsChecked)
|
||||
{
|
||||
studentParams.Visibility = ViewStates.Gone;
|
||||
profParams.Visibility = ViewStates.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
studentParams.Visibility = ViewStates.Visible;
|
||||
profParams.Visibility = ViewStates.Gone;
|
||||
}
|
||||
};
|
||||
calendar.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutString("Calendar", Calendar.Calendars[e.Position].Id).Apply();
|
||||
reminder.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutInt("Reminder", e.Position).Apply();
|
||||
group.ItemSelected += (s, e) =>
|
||||
prefs.Edit().PutString("Group", Data.Groups[e.Position].Id).Apply();
|
||||
|
||||
groupTitle.Click += (s, e) =>
|
||||
prefs.Edit().PutBoolean("AddGroupToHeader", groupTitle.Checked).Apply();
|
||||
|
||||
|
||||
forDay.Click += (s, e) => SetDate(0);
|
||||
forWeek.Click += (s, e) => SetDate(6);
|
||||
forMonth.Click += (s, e) => SetDate(30);
|
||||
forSemester.Click += (s, e) =>
|
||||
{
|
||||
Data.EndDate = DateTime.Today.Month > 8 ? new DateTime(DateTime.Today.Year + 1, 1, 1) : new DateTime(DateTime.Today.Year, 8, 31);
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
};
|
||||
|
||||
start.Click += Start_Click;
|
||||
end.Click += End_Click;
|
||||
|
||||
export.Click += Export_Click;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Menu stuff
|
||||
public override bool OnCreateOptionsMenu(IMenu menu)
|
||||
{
|
||||
MenuInflater.Inflate(Resource.Menu.MainContextMenu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear(bool keepPrevious = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.clearingStatus), ToastLength.Short).Show();
|
||||
Calendar.Clear(keepPrevious);
|
||||
Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.doneStatus), ToastLength.Short).Show();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(e.Message)
|
||||
.SetTitle(e.GetType().ToString())
|
||||
.SetPositiveButton("ОК", (IDialogInterfaceOnClickListener)null);
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnOptionsItemSelected(IMenuItem item)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder;
|
||||
Android.Support.V7.App.AlertDialog dialog;
|
||||
switch (item.ItemId)
|
||||
{
|
||||
case Resource.Id.about:
|
||||
StartActivity(new Intent(this, typeof(AboutActivity)));
|
||||
return true;
|
||||
case Resource.Id.email:
|
||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
||||
return true;
|
||||
|
||||
case Resource.Id.clear:
|
||||
builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(Resources.GetText(Resource.String.clearScheduleMessage))
|
||||
.SetTitle(Resources.GetText(Resource.String.clearScheduleTitle))
|
||||
.SetPositiveButton(Resources.GetText(Resource.String.clearUpcomingOption), (s, e) => Clear())
|
||||
.SetNegativeButton(Resources.GetText(Resource.String.clearAllOption), (s, e) => Clear(false))
|
||||
.SetNeutralButton(Resources.GetText(Resource.String.cancelOption), (IDialogInterfaceOnClickListener)null);
|
||||
|
||||
dialog = builder.Create();
|
||||
dialog.Show();
|
||||
|
||||
// Making links clickable
|
||||
dialog.FindViewById<TextView>(Android.Resource.Id.Message).MovementMethod = LinkMovementMethod.Instance;
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnOptionsItemSelected(item);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override void OnBackPressed() =>
|
||||
FinishAffinity(); // Close application
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
using Android;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Support.V4.Content;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Widget;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUT.Schedule.Activities
|
||||
{
|
||||
/// <summary>
|
||||
/// Splash screen activity. Loads init data
|
||||
/// </summary>
|
||||
[Activity(MainLauncher = true, Theme = "@style/AppTheme.Light.SplashScreen")]
|
||||
public class StartActivity : AppCompatActivity
|
||||
{
|
||||
TextView status;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
SetContentView(Resource.Layout.SplashScreen);
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
status = FindViewById<TextView>(Resource.Id.status);
|
||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.permissionsCheckStatus);
|
||||
|
||||
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteCalendar) != Permission.Granted)
|
||||
{
|
||||
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.WriteCalendar))
|
||||
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
||||
else
|
||||
RequestPermissions();
|
||||
}
|
||||
else
|
||||
Proceed();
|
||||
}
|
||||
|
||||
private async void Proceed()
|
||||
{
|
||||
try
|
||||
{
|
||||
status.Text = Resources.GetText(Resource.String.calendarLoadingStatus);
|
||||
Calendar.LoadCalendars();
|
||||
if (Calendar.Calendars.Count == 0)
|
||||
{
|
||||
ShowDialog(Resources.GetText(Resource.String.createCalendarTitle), Resources.GetText(Resource.String.createCalendarMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.facultiesLoadingStatus);
|
||||
await Parser.LoadFaculties();
|
||||
|
||||
status.Text = Resources.GetText(Resource.String.offsetDatesLoadingStatus);
|
||||
using HttpClient client = new HttpClient();
|
||||
Data.FirstWeekDay = int.Parse(await client.GetStringAsync("https://xfox111.net/schedule_offset.txt"));
|
||||
}
|
||||
catch(HttpRequestException e)
|
||||
{
|
||||
ShowDialog(e.Message, Resources.GetText(Resource.String.connectionFailMessage), Proceed, FinishAndRemoveTask, Resources.GetText(Resource.String.repeat), Resources.GetText(Resource.String.quit));
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ShowDialog(e.GetType().ToString(), e.Message, FinishAndRemoveTask);
|
||||
return;
|
||||
}
|
||||
StartActivity(new Intent(this, typeof(MainActivity)));
|
||||
}
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
|
||||
{
|
||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (grantResults.All(i => i == Permission.Granted))
|
||||
Proceed();
|
||||
else
|
||||
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
||||
}
|
||||
|
||||
private void RequestPermissions() =>
|
||||
ActivityCompat.RequestPermissions(this, new[]
|
||||
{
|
||||
Manifest.Permission.ReadCalendar,
|
||||
Manifest.Permission.WriteCalendar,
|
||||
Manifest.Permission.Internet
|
||||
}, 0);
|
||||
|
||||
private void ShowDialog(string title, string content, Action posAction = null, Action negAction = null, string posActionLabel = null, string negActionLabel = null)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(content)
|
||||
.SetTitle(title).SetPositiveButton(posActionLabel ?? "OK", (s, e) => posAction?.Invoke());
|
||||
|
||||
if (negAction != null)
|
||||
builder.SetNegativeButton(negActionLabel ?? Resources.GetText(Resource.String.close), (s, e) => negAction.Invoke());
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { } // Disables back button
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Net;
|
||||
using Android.Provider;
|
||||
using GUT.Schedule.Models;
|
||||
using Java.Util;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Calendar
|
||||
{
|
||||
/// <summary>
|
||||
/// List of all existing Google calendars on the device
|
||||
/// </summary>
|
||||
public static List<(string Id, string Name)> Calendars { get; private set; } = new List<(string Id, string Name)>();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all Google Accounts' calendars existing on the device and puts them to <see cref="Calendars"/>
|
||||
/// </summary>
|
||||
public static void LoadCalendars()
|
||||
{
|
||||
Calendars = new List<(string, string)>(); // Resetting current calendars list
|
||||
|
||||
// Building calendar data retrieval projections
|
||||
Uri calendarsUri = CalendarContract.Calendars.ContentUri;
|
||||
string[] calendarsProjection = {
|
||||
CalendarContract.Calendars.InterfaceConsts.Id,
|
||||
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
|
||||
CalendarContract.Calendars.InterfaceConsts.AccountName
|
||||
};
|
||||
|
||||
// Retrieving calendars data
|
||||
ICursor cursor = Application.Context.ContentResolver.Query(calendarsUri, calendarsProjection, null, null, null);
|
||||
|
||||
while (cursor.MoveToNext())
|
||||
Calendars.Add((cursor.GetString(0), $"{cursor.GetString(1)} ({cursor.GetString(2)})"));
|
||||
|
||||
cursor.Close();
|
||||
}
|
||||
|
||||
public static void Export(IEnumerable<Subject> schedule)
|
||||
{
|
||||
DataSet data = Data.DataSet;
|
||||
|
||||
foreach (Subject item in schedule)
|
||||
{
|
||||
ContentValues eventValues = new ContentValues();
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}.{1} {2} ({3})",
|
||||
item.Order,
|
||||
data.AddGroupToTitle ? $" [{item.Group}]" : "",
|
||||
item.Name,
|
||||
item.Type));
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Professor);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, string.Join(';', item.Cabinets));
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
||||
|
||||
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
||||
|
||||
// Settings reminder
|
||||
if(data.Reminder != -5)
|
||||
{
|
||||
ContentValues reminderValues = new ContentValues();
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||
|
||||
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Export(IEnumerable<CabinetSubject> schedule)
|
||||
{
|
||||
DataSet data = Data.DataSet;
|
||||
|
||||
foreach (CabinetSubject item in schedule)
|
||||
{
|
||||
ContentValues eventValues = new ContentValues();
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, data.Calendar);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}{1}. {2} ({3})",
|
||||
item.ProfessorSchedule ? "📚 " : (data.AddGroupToTitle ? $"[{data.Group}] " : ""),
|
||||
item.Order,
|
||||
item.Name,
|
||||
item.Type));
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, item.Opponent);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, item.Cabinet);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Availability, 0);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.HasAlarm, data.Reminder != -5);
|
||||
// For some reason Google calendars ignore HasAlarm = false and set reminder for 30 minutes. Local calendars don't seem to have this issue
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, item.StartTime.ToUnixTime());
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, item.EndTime.ToUnixTime());
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone, TimeZone.Default.ID);
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CustomAppPackage, Application.Context.PackageName);
|
||||
|
||||
Uri response = Application.Context.ContentResolver.Insert(CalendarContract.Events.ContentUri, eventValues);
|
||||
|
||||
// Settings reminder
|
||||
if(data.Reminder != -5)
|
||||
{
|
||||
ContentValues reminderValues = new ContentValues();
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, data.Reminder);
|
||||
|
||||
Application.Context.ContentResolver.Insert(CalendarContract.Reminders.ContentUri, reminderValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear(bool keepPrevious = true)
|
||||
{
|
||||
Uri contentUri = CalendarContract.Events.ContentUri;
|
||||
string selector = $"({CalendarContract.Events.InterfaceConsts.CustomAppPackage} == \"{Application.Context.PackageName}\") AND (deleted != 1)";
|
||||
if (keepPrevious)
|
||||
selector += $" AND (dtstart > {System.DateTime.Now.ToUnixTime()})";
|
||||
|
||||
string[] calendarsProjection = {
|
||||
CalendarContract.Events.InterfaceConsts.Id,
|
||||
CalendarContract.Events.InterfaceConsts.Dtstart,
|
||||
CalendarContract.Events.InterfaceConsts.CustomAppPackage,
|
||||
};
|
||||
|
||||
// Retrieving calendars data
|
||||
ICursor cursor = Application.Context.ContentResolver.Query(contentUri, calendarsProjection, selector, null, null);
|
||||
while (cursor.MoveToNext())
|
||||
Application.Context.ContentResolver.Delete(ContentUris.WithAppendedId(CalendarContract.Events.ContentUri, cursor.GetLong(0)), null, null);
|
||||
|
||||
cursor.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Android.Content;
|
||||
using Android.Widget;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets array as Spinner dropdown list content
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Array items type</typeparam>
|
||||
/// <param name="spinner">Spinner on which array will be assigned to</param>
|
||||
/// <param name="context">Current activity context. In most common cases <c>this</c> will do</param>
|
||||
/// <param name="array">Array of items to be displayed</param>
|
||||
public static void SetList<T>(this Spinner spinner, Context context, IEnumerable<T> array)
|
||||
{
|
||||
ArrayAdapter adapter = new ArrayAdapter(context, Resource.Layout.support_simple_spinner_dropdown_item, array.ToList());
|
||||
spinner.Adapter = adapter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see cref="DateTime"/> instance based on study week number, weekday and semester start day number
|
||||
/// </summary>
|
||||
/// <param name="week">Number of the study week</param>
|
||||
/// <param name="weekday">Weekday</param>
|
||||
/// <returns><see cref="DateTime"/> instance based on study week number, weekday and semester start day number</returns>
|
||||
public static DateTime GetDateFromWeeks(int week, int weekday)
|
||||
{
|
||||
DateTime dt = new DateTime(DateTime.Today.Year, DateTime.Today.Month >= 8 ? 9 : 2, Data.FirstWeekDay);
|
||||
|
||||
dt = dt.AddDays(--week * 7);
|
||||
dt = dt.AddDays(--weekday);
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="DateTime"/> to milliseconds count
|
||||
/// </summary>
|
||||
/// <remarks>In the nearest future we will be fucked because of that shit</remarks>
|
||||
/// <param name="dt"><see cref="DateTime"/> which is to be converted to UNIX time</param>
|
||||
/// <returns><see cref="long"/> which is represented by total milliseconds count passed since 1970</returns>
|
||||
public static long ToUnixTime(this DateTime dt) =>
|
||||
(long)dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
||||
|
||||
public static void SetContent(this HttpRequestMessage request, params (string key, string value)[] values)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
|
||||
Dictionary<string, string> body = new Dictionary<string, string>();
|
||||
foreach ((string key, string value) in values)
|
||||
body.Add(key, value);
|
||||
request.Content = new FormUrlEncodedContent(body);
|
||||
}
|
||||
public static async Task<string> GetString(this HttpResponseMessage response)
|
||||
{
|
||||
if (response == null)
|
||||
throw new ArgumentNullException(nameof(response));
|
||||
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
return Encoding.GetEncoding("Windows-1251").GetString(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
using Android.App;
|
||||
using System.Threading.Tasks;
|
||||
using Android.Content;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
/// <summary>
|
||||
/// Date picker
|
||||
/// </summary>
|
||||
public class DatePickerFragment : Android.Support.V4.App.DialogFragment, DatePickerDialog.IOnDateSetListener
|
||||
{
|
||||
DateTime _date;
|
||||
bool dismissed = false;
|
||||
public override Dialog OnCreateDialog(Bundle savedInstanceState) =>
|
||||
new DatePickerDialog(Activity, this, _date.Year, _date.Month - 1, _date.Day);
|
||||
|
||||
// Occures when user selected a date
|
||||
public void OnDateSet(DatePicker view, int year, int month, int dayOfMonth)
|
||||
{
|
||||
_date = view.DateTime;
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
public override void OnCancel(IDialogInterface dialog)
|
||||
{
|
||||
base.OnCancel(dialog);
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows date picker and waits for user input
|
||||
/// </summary>
|
||||
/// <param name="manager">Fragment manager of the current activity (In most common cases it is <c>this.FragmentManager</c>)</param>
|
||||
/// <param name="date">Date which is to be selected by default</param>
|
||||
/// <returns><see cref="DateTime"/> picked by user</returns>
|
||||
public async Task<DateTime> GetDate(Android.Support.V4.App.FragmentManager manager, DateTime date)
|
||||
{
|
||||
_date = date;
|
||||
Show(manager, "datePicker");
|
||||
|
||||
while (!dismissed)
|
||||
await Task.Delay(100);
|
||||
|
||||
return _date;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace GUT.Schedule.Models
|
||||
{
|
||||
public class CabinetSubject
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Cabinet { get; set; }
|
||||
public string Order { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public string Opponent { get; set; }
|
||||
public bool ProfessorSchedule { get; set; }
|
||||
|
||||
public CabinetSubject(string name, string type, string cabinet, string opponent, int year, int month, int day, string schedule, bool profSchedule)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
Cabinet = cabinet;
|
||||
Opponent = opponent;
|
||||
ProfessorSchedule = profSchedule;
|
||||
|
||||
string[] time = schedule.Split('-');
|
||||
|
||||
StartTime = new DateTime(year, month, day, int.Parse(time[0].Split('.')[0]), int.Parse(time[0].Split('.')[1]), 0);
|
||||
EndTime = new DateTime(year, month, day, int.Parse(time[1].Split('.')[0]), int.Parse(time[1].Split('.')[1]), 0);
|
||||
Order = time[0] switch
|
||||
{
|
||||
"09.00" => "1",
|
||||
"10.45" => "2",
|
||||
"13.00" => "3",
|
||||
"14.45" => "4",
|
||||
"16.30" => "5",
|
||||
"18.15" => "6",
|
||||
"20.00" => "7",
|
||||
"10.30" => "2", //Расписание для пар по физ-ре
|
||||
"12.00" => "3",
|
||||
"13.30" => "4",
|
||||
"15.00" => "5",
|
||||
"18.00" => "7",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using GUT.Schedule.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Data
|
||||
{
|
||||
public static List<(string Id, string Name)> Faculties { get; set; }
|
||||
public static List<(string Id, string Name)> Groups { get; set; }
|
||||
public static int FirstWeekDay { get; set; }
|
||||
public static DateTime StartDate { get; set; } = DateTime.Today;
|
||||
public static DateTime EndDate { get; set; } = DateTime.Today.AddDays(7);
|
||||
|
||||
/// <summary>
|
||||
/// Export parameters
|
||||
/// </summary>
|
||||
public static DataSet DataSet { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUT.Schedule.Models
|
||||
{
|
||||
public class DataSet
|
||||
{
|
||||
public string Calendar { get; set; }
|
||||
public string Faculty { get; set; }
|
||||
public int Course { get; set; }
|
||||
public string Group { get; set; }
|
||||
public int Reminder { get; set; }
|
||||
public bool AddGroupToTitle { get; set; }
|
||||
public HttpClient HttpClient { get; set; }
|
||||
public bool? IsProfessor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GUT.Schedule.Models
|
||||
{
|
||||
public class Subject
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Professor { get; set; }
|
||||
public string[] Cabinets { get; set; }
|
||||
public string Order { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public string Group { get; set; }
|
||||
|
||||
public static List<Subject> GetSubject(string name, string type, string professor, string place, int order, string[] weeks, int weekday, string group)
|
||||
{
|
||||
List<Subject> subjects = new List<Subject>();
|
||||
string[] cabinets = place.Replace("ауд.: ", "").Replace("; Б22", "").Split(';');
|
||||
string pair = order < 10 ? order.ToString() : $"Ф{order - 81}";
|
||||
|
||||
foreach (string week in weeks)
|
||||
subjects.Add(new Subject(name, type, professor, cabinets, pair, int.Parse(week), weekday, group));
|
||||
|
||||
return subjects;
|
||||
}
|
||||
|
||||
public Subject(string name, string type, string prof, string[] cabs, string order, int week, int weekday, string group)
|
||||
{
|
||||
Name = name;
|
||||
Type = type;
|
||||
Professor = prof;
|
||||
Cabinets = cabs;
|
||||
Order = order;
|
||||
Group = group;
|
||||
|
||||
StartTime = Extensions.GetDateFromWeeks(week, weekday);
|
||||
StartTime = StartTime.Add(TimeSpan.Parse(order switch
|
||||
{
|
||||
"1" => "9:00",
|
||||
"2" => "10:45",
|
||||
"3" => "13:00",
|
||||
"4" => "14:45",
|
||||
"5" => "16:30",
|
||||
"6" => "18:15",
|
||||
"7" => "20:00",
|
||||
"Ф1" => "9:00", //Расписание для пар по физ-ре
|
||||
"Ф2" => "10:30",
|
||||
"Ф3" => "12:00",
|
||||
"Ф4" => "13:30",
|
||||
"Ф5" => "15:00",
|
||||
"Ф6" => "16:30",
|
||||
"Ф7" => "18:00",
|
||||
_ => "9:00"
|
||||
}));
|
||||
EndTime = StartTime + TimeSpan.FromMinutes(order.Contains("Ф") ? 90 : 95);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
using AngleSharp.Dom;
|
||||
using AngleSharp.Html.Dom;
|
||||
using AngleSharp.Html.Parser;
|
||||
using GUT.Schedule.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Parser
|
||||
{
|
||||
public static async Task<List<Subject>> LoadSchedule()
|
||||
{
|
||||
List<Subject> schedule = new List<Subject>();
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "group_el", "0" },
|
||||
{ "kurs", Data.DataSet.Course.ToString() },
|
||||
{ "type_z", "1" },
|
||||
{ "faculty", Data.DataSet.Faculty },
|
||||
{ "group", Data.DataSet.Group },
|
||||
{ "ok", "Показать" },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(await response.Content.ReadAsStringAsync());
|
||||
|
||||
string groupName = Data.Groups.First(i => i.Id == Data.DataSet.Group).Name;
|
||||
|
||||
IHtmlCollection<IElement> pairs = doc.QuerySelectorAll(".pair");
|
||||
foreach (IElement item in pairs)
|
||||
{
|
||||
string name, type, professor, place;
|
||||
int order, weekday;
|
||||
string[] weeks;
|
||||
|
||||
name = item.QuerySelector(".subect strong")?.TextContent ?? "Неизвестный предмет (см. Расписание)";
|
||||
type = item.QuerySelector(".type").TextContent.Replace("(", "").Replace(")", "");
|
||||
professor = item.QuerySelector(".teacher")?.GetAttribute("title").Replace(";", "") ?? "";
|
||||
place = item.QuerySelector(".aud")?.TextContent ?? "СПбГУТ";
|
||||
order = int.Parse(item.GetAttribute("pair")) - 1;
|
||||
weeks = item.QuerySelector(".weeks").TextContent.Replace("(", "").Replace("н)", "").Split(", ");
|
||||
weekday = int.Parse(item.GetAttribute("weekday"));
|
||||
|
||||
schedule.AddRange(Subject.GetSubject(name, type, professor, place, order, weeks, weekday, groupName));
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
public static async Task LoadFaculties()
|
||||
{
|
||||
Data.Faculties = new List<(string, string)>();
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", "0" },
|
||||
{ "type_z", "1" },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrWhiteSpace(responseBody))
|
||||
throw new NullReferenceException("Расписание на текущий семестр еще не объявлено");
|
||||
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Faculties.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static async Task LoadGroups(string facultyId, int course)
|
||||
{
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", course.ToString() },
|
||||
{ "type_z", "1" },
|
||||
{ "faculty", facultyId },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
Data.Groups = new List<(string, string)>();
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Groups.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
static string GetCurrentSemester()
|
||||
{
|
||||
DateTime now = DateTime.Today;
|
||||
|
||||
if (now.Month > 8)
|
||||
return $"205.{now.Year - 2000}{now.Year - 1999}/1";
|
||||
else
|
||||
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
||||
}
|
||||
|
||||
public static async Task<List<CabinetSubject>> GetCabinetSchedule(HttpClient client, DateTime date, bool checkProfSchedule)
|
||||
{
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"https://cabs.itut.ru/cabinet/project/cabinet/forms/{(checkProfSchedule ? "pr_" : "")}raspisanie_kalendar.php");
|
||||
request.SetContent(
|
||||
("month", date.Month.ToString()),
|
||||
("year", date.Year.ToString()),
|
||||
("type_z", "0"));
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
string responseContent = await response.GetString().ConfigureAwait(false);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpRequestException(responseContent);
|
||||
|
||||
IHtmlDocument doc = new HtmlParser().ParseDocument(responseContent);
|
||||
List<CabinetSubject> schedule = new List<CabinetSubject>();
|
||||
|
||||
if(!checkProfSchedule)
|
||||
Data.DataSet.Group = doc.QuerySelector(".style_gr b").TextContent;
|
||||
|
||||
foreach (var i in doc.QuerySelectorAll("td").Where(i => i.GetAttribute("style") == "text-align: center; vertical-align: top"))
|
||||
for (int k = 0; k < i.QuerySelectorAll("i").Length; k++)
|
||||
{
|
||||
CabinetSubject item = new CabinetSubject(
|
||||
name: i.QuerySelectorAll("b")[k * 2 + 1].TextContent,
|
||||
type: i.QuerySelectorAll("i")[k].TextContent,
|
||||
cabinet: i.QuerySelectorAll("small")[k].NextSibling.TextContent.Replace("; Б22", ""),
|
||||
opponent: i.QuerySelectorAll("i")[k].NextSibling.NextSibling.NodeType == NodeType.Text ?
|
||||
i.QuerySelectorAll("i")[k].NextSibling.NextSibling.TextContent : "",
|
||||
year: date.Year,
|
||||
month: date.Month,
|
||||
day: int.Parse(i.ChildNodes[0].TextContent),
|
||||
schedule: i.QuerySelectorAll("b")[k * 2 + 2].TextContent,
|
||||
checkProfSchedule);
|
||||
schedule.Add(item);
|
||||
}
|
||||
|
||||
// Merge duplicating entries
|
||||
schedule.OrderByDescending(i => i.StartTime);
|
||||
for(int k = 1; k < schedule.Count; k++)
|
||||
if(schedule[k - 1].StartTime == schedule[k].StartTime &&
|
||||
schedule[k - 1].Name == schedule[k].Name &&
|
||||
schedule[k - 1].Type == schedule[k].Type)
|
||||
{
|
||||
schedule[k - 1].Opponent += "\n" + schedule[k].Opponent;
|
||||
schedule[k - 1].Cabinet += "; " + schedule[k].Cabinet;
|
||||
schedule.RemoveAt(k--);
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Support.V4.Text;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Text.Method;
|
||||
using Android.Widget;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace GUTSchedule.Droid.Activities
|
||||
{
|
||||
[Activity(Label = "@string/aboutTitle")]
|
||||
public class AboutActivity : AppCompatActivity
|
||||
{
|
||||
protected override async void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
(string name, string handle, string link)[] contacts = new (string, string, string)[]
|
||||
{
|
||||
(Resources.GetText(Resource.String.websiteContact), "https://xfox111.net", "https://xfox111.net"),
|
||||
(Resources.GetText(Resource.String.twitterContact), "@xfox111", "https://twitter.com/xfox111"),
|
||||
(Resources.GetText(Resource.String.vkontakteContact), "@xfox.mike", "https://vk.com/xfox.mike"),
|
||||
("LinkedIn", "@xfox", "https://linkedin.com/in/xfox"),
|
||||
("GitHub", "@xfox111", "https://github.com/xfox111"),
|
||||
};
|
||||
(string name, string link)[] links = new (string, string)[]
|
||||
{
|
||||
(Resources.GetText(Resource.String.privacyPolicyLink), "https://xfox111.net/Projects/GUTSchedule/PrivacyPolicy.txt"),
|
||||
("General Public License v3", "https://www.gnu.org/licenses/gpl-3.0"),
|
||||
(Resources.GetText(Resource.String.repositoryLink), "https://github.com/xfox111/gutschedule"),
|
||||
(Resources.GetText(Resource.String.notsLink), "http://tios.spbgut.ru/index.php"),
|
||||
(Resources.GetText(Resource.String.sutLink), "https://sut.ru"),
|
||||
};
|
||||
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.About);
|
||||
PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll);
|
||||
FindViewById<TextView>(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})";
|
||||
|
||||
FindViewById<Button>(Resource.Id.feedback).Click += (s, e) =>
|
||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("mailto:feedback@xfox111.net")));
|
||||
|
||||
FindViewById<TextView>(Resource.Id.contacts).SetText(
|
||||
HtmlCompat.FromHtml(string.Join("<br />", contacts.Select(i => $"<span>{i.name}:</span> <a href=\"{i.link}\">{i.handle}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.contacts).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.links).SetText(
|
||||
HtmlCompat.FromHtml(string.Join("<br />", links.Select(i => $"<a href=\"{i.link}\">{i.name}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.links).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
List<string> contributors = new List<string>();
|
||||
try
|
||||
{
|
||||
using HttpClient client = new HttpClient();
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/xfox111/gutschedule/contributors");
|
||||
request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string resposeContent = await response.Content.ReadAsStringAsync();
|
||||
dynamic parsedResponse = JsonConvert.DeserializeObject(resposeContent);
|
||||
|
||||
foreach (var i in parsedResponse)
|
||||
if (i.type == "User" && ((string)i.login).ToLower() != "xfox111")
|
||||
contributors.Add((string)i.login);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (contributors.Count > 0)
|
||||
{
|
||||
FindViewById<TextView>(Resource.Id.contributors).SetText(
|
||||
HtmlCompat.FromHtml(string.Join(", ", contributors.Select(i => $"<a href=\"https://github.com/{i}\">@{i}</a>")), HtmlCompat.FromHtmlModeLegacy),
|
||||
TextView.BufferType.Normal);
|
||||
FindViewById<TextView>(Resource.Id.contributors).MovementMethod = LinkMovementMethod.Instance;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.contributorsTitle).Visibility = Android.Views.ViewStates.Visible;
|
||||
FindViewById<TextView>(Resource.Id.contributors).Visibility = Android.Views.ViewStates.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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
|
||||
{
|
||||
status.Text = Resources.GetText(Resource.String.loadingStatus);
|
||||
|
||||
List<Occupation> schedule = await Parser.GetSchedule(MainActivity.ExportParameters);
|
||||
|
||||
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,335 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
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 GUTSchedule.Models;
|
||||
using GUTSchedule.Droid.Fragments;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUTSchedule.Droid.Activities
|
||||
{
|
||||
[Activity]
|
||||
public class MainActivity : AppCompatActivity
|
||||
{
|
||||
public static ExportParameters ExportParameters { get; set; }
|
||||
public static List<(string id, string name)> Faculties { get; set; }
|
||||
public static List<(string id, string name)> Groups { get; set; }
|
||||
public static bool AddGroupToTitle { get; set; }
|
||||
public static int SelectedCalendarIndex { get; set; }
|
||||
public static int Reminder { get; set; }
|
||||
|
||||
DateTime startDate = DateTime.Today;
|
||||
DateTime endDate = DateTime.Today.AddDays(7);
|
||||
|
||||
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 async 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, Faculties.Select(i => i.name));
|
||||
int s = 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
|
||||
|
||||
await Task.Delay(100);
|
||||
UpdateGroupsList();
|
||||
|
||||
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 = endDate.ToShortDateString();
|
||||
start.Text = 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 void Export_Click(object sender, EventArgs e)
|
||||
{
|
||||
error.Visibility = ViewStates.Gone;
|
||||
|
||||
if (startDate > endDate)
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.invalidDateRangeError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
if (authorize.Checked)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text))
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.invalidAuthorizationError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
ExportParameters = new CabinetExportParameters
|
||||
{
|
||||
Email = email.Text,
|
||||
Password = password.Text,
|
||||
EndDate = endDate,
|
||||
StartDate = startDate
|
||||
};
|
||||
|
||||
// Если ты это читаешь и у тебя возникли вопросы по типу "А какого хуя творится в коде ниже?!", то во-первых:
|
||||
// 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 (Groups.Count < 1)
|
||||
{
|
||||
error.Text = Resources.GetText(Resource.String.groupSelectionError);
|
||||
error.Visibility = ViewStates.Visible;
|
||||
return;
|
||||
}
|
||||
|
||||
ExportParameters = new DefaultExportParameters
|
||||
{
|
||||
EndDate = endDate,
|
||||
StartDate = startDate,
|
||||
Course = (course.SelectedItemPosition + 1).ToString(),
|
||||
FacultyId = Faculties[faculty.SelectedItemPosition].id,
|
||||
GroupId = Groups[group.SelectedItemPosition].id,
|
||||
};
|
||||
}
|
||||
|
||||
AddGroupToTitle = groupTitle.Checked;
|
||||
SelectedCalendarIndex = calendar.SelectedItemPosition;
|
||||
Reminder = (reminder.SelectedItemPosition - 1) * 5;
|
||||
|
||||
StartActivity(new Intent(this, typeof(ExportActivity)));
|
||||
}
|
||||
|
||||
private async void End_Click(object sender, EventArgs e)
|
||||
{
|
||||
endDate = await new DatePickerFragment().GetDate(SupportFragmentManager, endDate);
|
||||
end.Text = endDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void Start_Click(object sender, EventArgs e)
|
||||
{
|
||||
startDate = await new DatePickerFragment().GetDate(SupportFragmentManager, startDate);
|
||||
start.Text = startDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void UpdateGroupsList()
|
||||
{
|
||||
if (course.SelectedItem == null)
|
||||
return;
|
||||
|
||||
Groups = await Parser.GetGroups(Faculties[faculty.SelectedItemPosition].id, (course.SelectedItemPosition + 1).ToString());
|
||||
group.SetList(this, Groups.Select(i => i.name));
|
||||
|
||||
int s = Groups?.FindIndex(i => i.id == prefs.GetString("Group", "-123")) ?? 0;
|
||||
group.SetSelection(s == -1 ? 0 : s);
|
||||
}
|
||||
|
||||
private void SetDate(int days)
|
||||
{
|
||||
endDate = startDate.AddDays(days);
|
||||
end.Text = 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", 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", 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) =>
|
||||
{
|
||||
if (DateTime.Today.Month == 1)
|
||||
endDate = new DateTime(DateTime.Today.Year, 1, 31);
|
||||
else if (DateTime.Today.Month > 8)
|
||||
endDate = new DateTime(DateTime.Today.Year + 1, 1, 31);
|
||||
else
|
||||
endDate = new DateTime(DateTime.Today.Year, 8, 31);
|
||||
end.Text = 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,110 @@
|
||||
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);
|
||||
MainActivity.Faculties = await Parser.GetFaculties();
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
ShowDialog(e.Message, Resources.GetText(Resource.String.connectionFailMessage), Proceed, FinishAndRemoveTask, Resources.GetText(Resource.String.repeat), Resources.GetText(Resource.String.quit));
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ShowDialog(e.GetType().ToString(), e.Message, FinishAndRemoveTask);
|
||||
return;
|
||||
}
|
||||
StartActivity(new Intent(this, typeof(MainActivity)));
|
||||
}
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
|
||||
{
|
||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (grantResults.All(i => i == Permission.Granted))
|
||||
Proceed();
|
||||
else
|
||||
ShowDialog(Resources.GetText(Resource.String.calendarAccessTitle), Resources.GetText(Resource.String.calendarAccessRationale), RequestPermissions);
|
||||
}
|
||||
|
||||
private void RequestPermissions() =>
|
||||
ActivityCompat.RequestPermissions(this, new[]
|
||||
{
|
||||
Android.Manifest.Permission.ReadCalendar,
|
||||
Android.Manifest.Permission.WriteCalendar,
|
||||
Android.Manifest.Permission.Internet
|
||||
}, 0);
|
||||
|
||||
private void ShowDialog(string title, string content, Action posAction = null, Action negAction = null, string posActionLabel = null, string negActionLabel = null)
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage(content)
|
||||
.SetTitle(title).SetPositiveButton(posActionLabel ?? "OK", (s, e) => posAction?.Invoke());
|
||||
|
||||
if (negAction != null)
|
||||
builder.SetNegativeButton(negActionLabel ?? Resources.GetText(Resource.String.close), (s, e) => negAction.Invoke());
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { } // Disables back button
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Net;
|
||||
using Android.Provider;
|
||||
using GUTSchedule.Droid.Activities;
|
||||
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<Occupation> schedule)
|
||||
{
|
||||
foreach (Occupation item in schedule)
|
||||
{
|
||||
ContentValues eventValues = new ContentValues();
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, Calendars[MainActivity.SelectedCalendarIndex].Id);
|
||||
|
||||
eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, string.Format("{0}.{1} {2} ({3})",
|
||||
item.Order,
|
||||
MainActivity.AddGroupToTitle && !string.IsNullOrWhiteSpace(item.Group) ? $" [{item.Group}]" : "",
|
||||
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, MainActivity.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 (MainActivity.Reminder != -5)
|
||||
{
|
||||
ContentValues reminderValues = new ContentValues();
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, long.Parse(response.LastPathSegment));
|
||||
reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, MainActivity.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>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GUT.Schedule</RootNamespace>
|
||||
<AssemblyName>GUT.Schedule</AssemblyName>
|
||||
<RootNamespace>GUTSchedule.Droid</RootNamespace>
|
||||
<AssemblyName>GUTSchedule.Droid</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AndroidApplication>True</AndroidApplication>
|
||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||
@@ -93,18 +93,13 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Activities\AboutActivity.cs" />
|
||||
<Compile Include="Calendar.cs" />
|
||||
<Compile Include="Models\Data.cs" />
|
||||
<Compile Include="Fragments\DatePickerFragment.cs" />
|
||||
<Compile Include="Activities\ExportActivity.cs" />
|
||||
<Compile Include="Extensions.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="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Activities\StartActivity.cs" />
|
||||
<Compile Include="Models\Subject.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
@@ -133,18 +128,12 @@
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp">
|
||||
<Version>0.13.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CSharp">
|
||||
<Version>4.7.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>12.0.3</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Net.Http">
|
||||
<Version>4.3.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.3" />
|
||||
@@ -174,15 +163,18 @@
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Assets\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\values\strings.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\values-ru\strings.xml" />
|
||||
</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" />
|
||||
<!-- 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.
|
||||
@@ -9,9 +9,9 @@
|
||||
// </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()
|
||||
{
|
||||
global::Xamarin.Essentials.Resource.Attribute.alpha = global::GUT.Schedule.Resource.Attribute.alpha;
|
||||
global::Xamarin.Essentials.Resource.Attribute.coordinatorLayoutStyle = global::GUT.Schedule.Resource.Attribute.coordinatorLayoutStyle;
|
||||
global::Xamarin.Essentials.Resource.Attribute.font = global::GUT.Schedule.Resource.Attribute.font;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderAuthority = global::GUT.Schedule.Resource.Attribute.fontProviderAuthority;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderCerts = global::GUT.Schedule.Resource.Attribute.fontProviderCerts;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchStrategy = global::GUT.Schedule.Resource.Attribute.fontProviderFetchStrategy;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchTimeout = global::GUT.Schedule.Resource.Attribute.fontProviderFetchTimeout;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderPackage = global::GUT.Schedule.Resource.Attribute.fontProviderPackage;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderQuery = global::GUT.Schedule.Resource.Attribute.fontProviderQuery;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontStyle = global::GUT.Schedule.Resource.Attribute.fontStyle;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontVariationSettings = global::GUT.Schedule.Resource.Attribute.fontVariationSettings;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontWeight = global::GUT.Schedule.Resource.Attribute.fontWeight;
|
||||
global::Xamarin.Essentials.Resource.Attribute.keylines = global::GUT.Schedule.Resource.Attribute.keylines;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchor = global::GUT.Schedule.Resource.Attribute.layout_anchor;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchorGravity = global::GUT.Schedule.Resource.Attribute.layout_anchorGravity;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_behavior = global::GUT.Schedule.Resource.Attribute.layout_behavior;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_dodgeInsetEdges = global::GUT.Schedule.Resource.Attribute.layout_dodgeInsetEdges;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_insetEdge = global::GUT.Schedule.Resource.Attribute.layout_insetEdge;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_keyline = global::GUT.Schedule.Resource.Attribute.layout_keyline;
|
||||
global::Xamarin.Essentials.Resource.Attribute.statusBarBackground = global::GUT.Schedule.Resource.Attribute.statusBarBackground;
|
||||
global::Xamarin.Essentials.Resource.Attribute.ttcIndex = global::GUT.Schedule.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_divider_color = global::GUT.Schedule.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_title_color = global::GUT.Schedule.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_icon_bg_color = global::GUT.Schedule.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.secondary_text_default_material_light = global::GUT.Schedule.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_min_padding = global::GUT.Schedule.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_vertical_material = global::GUT.Schedule.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_vertical_material = global::GUT.Schedule.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_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_width = global::GUT.Schedule.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_text_size = global::GUT.Schedule.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_content_margin_start = global::GUT.Schedule.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_width = global::GUT.Schedule.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_media_narrow_margin = global::GUT.Schedule.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_side_padding_top = global::GUT.Schedule.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_size_as_large = global::GUT.Schedule.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_top_pad = global::GUT.Schedule.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.Drawable.notification_action_background = global::GUT.Schedule.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_low = global::GUT.Schedule.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_pressed = global::GUT.Schedule.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_pressed = global::GUT.Schedule.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_template_icon_bg = global::GUT.Schedule.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_tile_bg = global::GUT.Schedule.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.Id.action_container = global::GUT.Schedule.Resource.Id.action_container;
|
||||
global::Xamarin.Essentials.Resource.Id.action_divider = global::GUT.Schedule.Resource.Id.action_divider;
|
||||
global::Xamarin.Essentials.Resource.Id.action_image = global::GUT.Schedule.Resource.Id.action_image;
|
||||
global::Xamarin.Essentials.Resource.Id.action_text = global::GUT.Schedule.Resource.Id.action_text;
|
||||
global::Xamarin.Essentials.Resource.Id.actions = global::GUT.Schedule.Resource.Id.actions;
|
||||
global::Xamarin.Essentials.Resource.Id.all = global::GUT.Schedule.Resource.Id.all;
|
||||
global::Xamarin.Essentials.Resource.Id.async = global::GUT.Schedule.Resource.Id.async;
|
||||
global::Xamarin.Essentials.Resource.Id.blocking = global::GUT.Schedule.Resource.Id.blocking;
|
||||
global::Xamarin.Essentials.Resource.Id.bottom = global::GUT.Schedule.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_menu_item_icon = global::GUT.Schedule.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_items = global::GUT.Schedule.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.center = global::GUT.Schedule.Resource.Id.center;
|
||||
global::Xamarin.Essentials.Resource.Id.center_horizontal = global::GUT.Schedule.Resource.Id.center_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.center_vertical = global::GUT.Schedule.Resource.Id.center_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.chronometer = global::GUT.Schedule.Resource.Id.chronometer;
|
||||
global::Xamarin.Essentials.Resource.Id.clip_horizontal = global::GUT.Schedule.Resource.Id.clip_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.clip_vertical = global::GUT.Schedule.Resource.Id.clip_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.end = global::GUT.Schedule.Resource.Id.end;
|
||||
global::Xamarin.Essentials.Resource.Id.fill = global::GUT.Schedule.Resource.Id.fill;
|
||||
global::Xamarin.Essentials.Resource.Id.fill_horizontal = global::GUT.Schedule.Resource.Id.fill_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.fill_vertical = global::GUT.Schedule.Resource.Id.fill_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.forever = global::GUT.Schedule.Resource.Id.forever;
|
||||
global::Xamarin.Essentials.Resource.Id.icon = global::GUT.Schedule.Resource.Id.icon;
|
||||
global::Xamarin.Essentials.Resource.Id.icon_group = global::GUT.Schedule.Resource.Id.icon_group;
|
||||
global::Xamarin.Essentials.Resource.Id.info = global::GUT.Schedule.Resource.Id.info;
|
||||
global::Xamarin.Essentials.Resource.Id.italic = global::GUT.Schedule.Resource.Id.italic;
|
||||
global::Xamarin.Essentials.Resource.Id.left = global::GUT.Schedule.Resource.Id.left;
|
||||
global::Xamarin.Essentials.Resource.Id.line1 = global::GUT.Schedule.Resource.Id.line1;
|
||||
global::Xamarin.Essentials.Resource.Id.line3 = global::GUT.Schedule.Resource.Id.line3;
|
||||
global::Xamarin.Essentials.Resource.Id.none = global::GUT.Schedule.Resource.Id.none;
|
||||
global::Xamarin.Essentials.Resource.Id.normal = global::GUT.Schedule.Resource.Id.normal;
|
||||
global::Xamarin.Essentials.Resource.Id.notification_background = global::GUT.Schedule.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_container = global::GUT.Schedule.Resource.Id.notification_main_column_container;
|
||||
global::Xamarin.Essentials.Resource.Id.right = global::GUT.Schedule.Resource.Id.right;
|
||||
global::Xamarin.Essentials.Resource.Id.right_icon = global::GUT.Schedule.Resource.Id.right_icon;
|
||||
global::Xamarin.Essentials.Resource.Id.right_side = global::GUT.Schedule.Resource.Id.right_side;
|
||||
global::Xamarin.Essentials.Resource.Id.start = global::GUT.Schedule.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_unhandled_key_event_manager = global::GUT.Schedule.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.text = global::GUT.Schedule.Resource.Id.text;
|
||||
global::Xamarin.Essentials.Resource.Id.text2 = global::GUT.Schedule.Resource.Id.text2;
|
||||
global::Xamarin.Essentials.Resource.Id.time = global::GUT.Schedule.Resource.Id.time;
|
||||
global::Xamarin.Essentials.Resource.Id.title = global::GUT.Schedule.Resource.Id.title;
|
||||
global::Xamarin.Essentials.Resource.Id.top = global::GUT.Schedule.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.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_row = global::GUT.Schedule.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_tombstone = global::GUT.Schedule.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_icon_group = global::GUT.Schedule.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_time = global::GUT.Schedule.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.Style.TextAppearance_Compat_Notification = global::GUT.Schedule.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_Line2 = global::GUT.Schedule.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_Title = global::GUT.Schedule.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_NotificationActionText = global::GUT.Schedule.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.Xml.xamarin_essentials_fileprovider_file_paths = global::GUT.Schedule.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_alpha = global::GUT.Schedule.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_color = global::GUT.Schedule.Resource.Styleable.ColorStateListItem_android_color;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_keylines = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_keylines;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::GUT.Schedule.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_android_layout_gravity = global::GUT.Schedule.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_anchorGravity = global::GUT.Schedule.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_dodgeInsetEdges = global::GUT.Schedule.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_keyline = global::GUT.Schedule.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily = global::GUT.Schedule.Resource.Styleable.FontFamily;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderAuthority = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderAuthority;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderCerts = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderCerts;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderFetchStrategy;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderFetchTimeout;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderPackage = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderPackage;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderQuery = global::GUT.Schedule.Resource.Styleable.FontFamily_fontProviderQuery;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont = global::GUT.Schedule.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_fontStyle = global::GUT.Schedule.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_fontWeight = global::GUT.Schedule.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_font = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_font;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontStyle = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontStyle;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontVariationSettings;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontWeight = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_fontWeight;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_ttcIndex = global::GUT.Schedule.Resource.Styleable.FontFamilyFont_ttcIndex;
|
||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor = global::GUT.Schedule.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_centerX = global::GUT.Schedule.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_endColor = global::GUT.Schedule.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_endY = global::GUT.Schedule.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_startColor = global::GUT.Schedule.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_startY = global::GUT.Schedule.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_type = global::GUT.Schedule.Resource.Styleable.GradientColor_android_type;
|
||||
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem = global::GUT.Schedule.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_offset = global::GUT.Schedule.Resource.Styleable.GradientColorItem_android_offset;
|
||||
global::Xamarin.Essentials.Resource.Attribute.alpha = global::GUTSchedule.Droid.Resource.Attribute.alpha;
|
||||
global::Xamarin.Essentials.Resource.Attribute.coordinatorLayoutStyle = global::GUTSchedule.Droid.Resource.Attribute.coordinatorLayoutStyle;
|
||||
global::Xamarin.Essentials.Resource.Attribute.font = global::GUTSchedule.Droid.Resource.Attribute.font;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderAuthority = global::GUTSchedule.Droid.Resource.Attribute.fontProviderAuthority;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderCerts = global::GUTSchedule.Droid.Resource.Attribute.fontProviderCerts;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchStrategy = global::GUTSchedule.Droid.Resource.Attribute.fontProviderFetchStrategy;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchTimeout = global::GUTSchedule.Droid.Resource.Attribute.fontProviderFetchTimeout;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderPackage = global::GUTSchedule.Droid.Resource.Attribute.fontProviderPackage;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontProviderQuery = global::GUTSchedule.Droid.Resource.Attribute.fontProviderQuery;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontStyle = global::GUTSchedule.Droid.Resource.Attribute.fontStyle;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontVariationSettings = global::GUTSchedule.Droid.Resource.Attribute.fontVariationSettings;
|
||||
global::Xamarin.Essentials.Resource.Attribute.fontWeight = global::GUTSchedule.Droid.Resource.Attribute.fontWeight;
|
||||
global::Xamarin.Essentials.Resource.Attribute.keylines = global::GUTSchedule.Droid.Resource.Attribute.keylines;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchor = global::GUTSchedule.Droid.Resource.Attribute.layout_anchor;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_anchorGravity = global::GUTSchedule.Droid.Resource.Attribute.layout_anchorGravity;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_behavior = global::GUTSchedule.Droid.Resource.Attribute.layout_behavior;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_dodgeInsetEdges = global::GUTSchedule.Droid.Resource.Attribute.layout_dodgeInsetEdges;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_insetEdge = global::GUTSchedule.Droid.Resource.Attribute.layout_insetEdge;
|
||||
global::Xamarin.Essentials.Resource.Attribute.layout_keyline = global::GUTSchedule.Droid.Resource.Attribute.layout_keyline;
|
||||
global::Xamarin.Essentials.Resource.Attribute.statusBarBackground = global::GUTSchedule.Droid.Resource.Attribute.statusBarBackground;
|
||||
global::Xamarin.Essentials.Resource.Attribute.ttcIndex = global::GUTSchedule.Droid.Resource.Attribute.ttcIndex;
|
||||
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::GUTSchedule.Droid.Resource.Color.browser_actions_divider_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::GUTSchedule.Droid.Resource.Color.browser_actions_title_color;
|
||||
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::GUTSchedule.Droid.Resource.Color.notification_icon_bg_color;
|
||||
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::GUTSchedule.Droid.Resource.Color.secondary_text_default_material_light;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.browser_actions_context_menu_min_padding;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.compat_button_inset_vertical_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::GUTSchedule.Droid.Resource.Dimension.compat_button_padding_vertical_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::GUTSchedule.Droid.Resource.Dimension.compat_notification_large_icon_max_height;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_action_icon_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::GUTSchedule.Droid.Resource.Dimension.notification_big_circle_margin;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_large_icon_height;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_main_column_padding_top;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_right_icon_size;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_small_icon_background_padding;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_subtext_size;
|
||||
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::GUTSchedule.Droid.Resource.Dimension.notification_top_pad_large_text;
|
||||
global::Xamarin.Essentials.Resource.Drawable.notification_action_background = global::GUTSchedule.Droid.Resource.Drawable.notification_action_background;
|
||||
global::Xamarin.Essentials.Resource.Drawable.notification_bg = global::GUTSchedule.Droid.Resource.Drawable.notification_bg;
|
||||
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::GUTSchedule.Droid.Resource.Drawable.notification_bg_low_normal;
|
||||
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::GUTSchedule.Droid.Resource.Drawable.notification_bg_normal;
|
||||
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::GUTSchedule.Droid.Resource.Drawable.notification_icon_background;
|
||||
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::GUTSchedule.Droid.Resource.Drawable.notification_template_icon_low_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::GUTSchedule.Droid.Resource.Drawable.notify_panel_notification_icon_bg;
|
||||
global::Xamarin.Essentials.Resource.Id.action_container = global::GUTSchedule.Droid.Resource.Id.action_container;
|
||||
global::Xamarin.Essentials.Resource.Id.action_divider = global::GUTSchedule.Droid.Resource.Id.action_divider;
|
||||
global::Xamarin.Essentials.Resource.Id.action_image = global::GUTSchedule.Droid.Resource.Id.action_image;
|
||||
global::Xamarin.Essentials.Resource.Id.action_text = global::GUTSchedule.Droid.Resource.Id.action_text;
|
||||
global::Xamarin.Essentials.Resource.Id.actions = global::GUTSchedule.Droid.Resource.Id.actions;
|
||||
global::Xamarin.Essentials.Resource.Id.all = global::GUTSchedule.Droid.Resource.Id.all;
|
||||
global::Xamarin.Essentials.Resource.Id.async = global::GUTSchedule.Droid.Resource.Id.async;
|
||||
global::Xamarin.Essentials.Resource.Id.blocking = global::GUTSchedule.Droid.Resource.Id.blocking;
|
||||
global::Xamarin.Essentials.Resource.Id.bottom = global::GUTSchedule.Droid.Resource.Id.bottom;
|
||||
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::GUTSchedule.Droid.Resource.Id.browser_actions_menu_item_icon;
|
||||
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::GUTSchedule.Droid.Resource.Id.browser_actions_menu_items;
|
||||
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::GUTSchedule.Droid.Resource.Id.center;
|
||||
global::Xamarin.Essentials.Resource.Id.center_horizontal = global::GUTSchedule.Droid.Resource.Id.center_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.center_vertical = global::GUTSchedule.Droid.Resource.Id.center_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.chronometer = global::GUTSchedule.Droid.Resource.Id.chronometer;
|
||||
global::Xamarin.Essentials.Resource.Id.clip_horizontal = global::GUTSchedule.Droid.Resource.Id.clip_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.clip_vertical = global::GUTSchedule.Droid.Resource.Id.clip_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.end = global::GUTSchedule.Droid.Resource.Id.end;
|
||||
global::Xamarin.Essentials.Resource.Id.fill = global::GUTSchedule.Droid.Resource.Id.fill;
|
||||
global::Xamarin.Essentials.Resource.Id.fill_horizontal = global::GUTSchedule.Droid.Resource.Id.fill_horizontal;
|
||||
global::Xamarin.Essentials.Resource.Id.fill_vertical = global::GUTSchedule.Droid.Resource.Id.fill_vertical;
|
||||
global::Xamarin.Essentials.Resource.Id.forever = global::GUTSchedule.Droid.Resource.Id.forever;
|
||||
global::Xamarin.Essentials.Resource.Id.icon = global::GUTSchedule.Droid.Resource.Id.icon;
|
||||
global::Xamarin.Essentials.Resource.Id.icon_group = global::GUTSchedule.Droid.Resource.Id.icon_group;
|
||||
global::Xamarin.Essentials.Resource.Id.info = global::GUTSchedule.Droid.Resource.Id.info;
|
||||
global::Xamarin.Essentials.Resource.Id.italic = global::GUTSchedule.Droid.Resource.Id.italic;
|
||||
global::Xamarin.Essentials.Resource.Id.left = global::GUTSchedule.Droid.Resource.Id.left;
|
||||
global::Xamarin.Essentials.Resource.Id.line1 = global::GUTSchedule.Droid.Resource.Id.line1;
|
||||
global::Xamarin.Essentials.Resource.Id.line3 = global::GUTSchedule.Droid.Resource.Id.line3;
|
||||
global::Xamarin.Essentials.Resource.Id.none = global::GUTSchedule.Droid.Resource.Id.none;
|
||||
global::Xamarin.Essentials.Resource.Id.normal = global::GUTSchedule.Droid.Resource.Id.normal;
|
||||
global::Xamarin.Essentials.Resource.Id.notification_background = global::GUTSchedule.Droid.Resource.Id.notification_background;
|
||||
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::GUTSchedule.Droid.Resource.Id.notification_main_column_container;
|
||||
global::Xamarin.Essentials.Resource.Id.right = global::GUTSchedule.Droid.Resource.Id.right;
|
||||
global::Xamarin.Essentials.Resource.Id.right_icon = global::GUTSchedule.Droid.Resource.Id.right_icon;
|
||||
global::Xamarin.Essentials.Resource.Id.right_side = global::GUTSchedule.Droid.Resource.Id.right_side;
|
||||
global::Xamarin.Essentials.Resource.Id.start = global::GUTSchedule.Droid.Resource.Id.start;
|
||||
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::GUTSchedule.Droid.Resource.Id.tag_unhandled_key_event_manager;
|
||||
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::GUTSchedule.Droid.Resource.Id.text;
|
||||
global::Xamarin.Essentials.Resource.Id.text2 = global::GUTSchedule.Droid.Resource.Id.text2;
|
||||
global::Xamarin.Essentials.Resource.Id.time = global::GUTSchedule.Droid.Resource.Id.time;
|
||||
global::Xamarin.Essentials.Resource.Id.title = global::GUTSchedule.Droid.Resource.Id.title;
|
||||
global::Xamarin.Essentials.Resource.Id.top = global::GUTSchedule.Droid.Resource.Id.top;
|
||||
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::GUTSchedule.Droid.Resource.Layout.browser_actions_context_menu_page;
|
||||
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::GUTSchedule.Droid.Resource.Layout.notification_action;
|
||||
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::GUTSchedule.Droid.Resource.Layout.notification_template_custom_big;
|
||||
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::GUTSchedule.Droid.Resource.Layout.notification_template_part_chronometer;
|
||||
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::GUTSchedule.Droid.Resource.String.status_bar_notification_info_overflow;
|
||||
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::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Info;
|
||||
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::GUTSchedule.Droid.Resource.Style.TextAppearance_Compat_Notification_Time;
|
||||
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::GUTSchedule.Droid.Resource.Style.Widget_Compat_NotificationActionContainer;
|
||||
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::GUTSchedule.Droid.Resource.Style.Widget_Support_CoordinatorLayout;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem;
|
||||
global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_alpha = global::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem_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::GUTSchedule.Droid.Resource.Styleable.ColorStateListItem_android_color;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_keylines = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_keylines;
|
||||
global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily = global::GUTSchedule.Droid.Resource.Styleable.FontFamily;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderAuthority = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderAuthority;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderCerts = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderCerts;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderPackage = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderPackage;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderQuery = global::GUTSchedule.Droid.Resource.Styleable.FontFamily_fontProviderQuery;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_font = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_font;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontStyle = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontStyle;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontWeight = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_fontWeight;
|
||||
global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_ttcIndex = global::GUTSchedule.Droid.Resource.Styleable.FontFamilyFont_ttcIndex;
|
||||
global::Xamarin.Essentials.Resource.Styleable.GradientColor = global::GUTSchedule.Droid.Resource.Styleable.GradientColor;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_centerX;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_endColor;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_endY;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_startColor;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_startY;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColor_android_type;
|
||||
global::Xamarin.Essentials.Resource.Styleable.GradientColorItem = global::GUTSchedule.Droid.Resource.Styleable.GradientColorItem;
|
||||
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::GUTSchedule.Droid.Resource.Styleable.GradientColorItem_android_offset;
|
||||
}
|
||||
|
||||
public partial class Animation
|
||||
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
@@ -14,7 +14,6 @@
|
||||
<ProgressBar
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:indeterminateTint="#fff"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="20dp"/>
|
||||
|
||||
@@ -23,7 +22,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/loadingStatus"
|
||||
android:textColor="#fff"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_gravity="center_horizontal"
|
||||
/>
|
||||
</LinearLayout>
|
||||
@@ -22,6 +22,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/appName"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="36dp"/>
|
||||
|
||||
<ProgressBar
|
||||
@@ -35,6 +36,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="@string/initializationStatus"
|
||||
android:textSize="20dp"/>
|
||||
</LinearLayout>
|
||||
@@ -45,6 +47,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="v$(Build.BuildNumber) (ci-id #$(Build.BuildId))"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -47,7 +47,7 @@
|
||||
<string name="addGroupToTitleCheckbox">Добавить номер группы в заголовок</string>
|
||||
<string name="titleNote">(i) Не касается преподавательского расписания</string>
|
||||
|
||||
<string name="destinationCalendarSpinner">Конечый календарь</string>
|
||||
<string name="destinationCalendarSpinner">Конечный календарь</string>
|
||||
|
||||
<string name="addScheduleButton">Добавить расписание</string>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<string name="forSemesterButton">For semester</string>
|
||||
|
||||
<string name="reminderSpinner">Set reminders for</string>
|
||||
<string name="reminderNote">(i) Attention, for cloud-based Google calendars Google automatically sets reminders for 30 minutes if there\'s no reminder set by user</string>
|
||||
<string name="reminderNote">(i) Attention, if you choose \"None\" for cloud-based Google calendars Google sets default reminder for events automatically sets reminders for 30 minutes if there\'s no reminder set by user</string>
|
||||
<string name="noReminderOption">None</string>
|
||||
<string name="inTimeReminderOption">At the start of event</string>
|
||||
<string name="fiveMinuteReminderOption">5 minutes</string>
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<string name="addScheduleButton">Add schedule</string>
|
||||
|
||||
<string name="copyrights">©2020 Michael Gordeev, INS, IS-907</string>
|
||||
<string name="copyrights">©2020 Michael Gordeev, INS, ICT-907</string>
|
||||
|
||||
<string name="clearCalendarOption">Clear schedule</string>
|
||||
<string name="reportErrorOption">Report error</string>
|
||||
@@ -79,7 +79,7 @@
|
||||
<!-- AboutActivity -->
|
||||
<string name="aboutTitle">About application</string>
|
||||
<string name="appDescription">Application for SPbSUT professors\' and students\' schedule export</string>
|
||||
<string name="developedBy">Developed by Michael Gordeev (IS-907, INS) in the \"Technologies of Informational and Educational Systems\" Research Facility</string>
|
||||
<string name="developedBy">Developed by Michael Gordeev (ICT-907, INS) in the \"Technologies of Informational and Educational Systems\" Research Facility</string>
|
||||
<string name="contributorsTitle">Contributors</string>
|
||||
|
||||
<string name="specialThanksTitle">Special thanks</string>
|
||||
@@ -15,7 +15,6 @@
|
||||
<item name="android:navigationBarColor">@color/colorPrimary</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
<item name="android:windowBackground">@color/colorPrimary</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
<item name="android:indeterminateTint">@android:color/white</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,24 @@
|
||||
<Application
|
||||
x:Class="GUTSchedule.UWP.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
RequestedTheme="Light">
|
||||
|
||||
<Application.Resources>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="Margin" Value="2"/>
|
||||
</Style>
|
||||
<Style TargetType="ComboBox">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
|
||||
</Style>
|
||||
<Style TargetType="CalendarDatePicker">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="Margin" Value="2"/>
|
||||
</Style>
|
||||
<Color x:Key="SystemAccentColor">#ff8000</Color>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using GUTSchedule.UWP.Pages;
|
||||
|
||||
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()
|
||||
{
|
||||
if ((new string[] { "ua", "ru", "by", "kz", "kg", "md", "lv", "ee" }).Contains(Windows.System.UserProfile.GlobalizationPreferences.Languages[0].Split('-')[0]))
|
||||
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "ru";
|
||||
else
|
||||
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "en";
|
||||
|
||||
InitializeComponent();
|
||||
UnhandledException += OnError;
|
||||
}
|
||||
|
||||
private async void OnError(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
await new MessageDialog(e.Message, e.GetType().ToString()).ShowAsync();
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (!(Window.Current.Content is Frame rootFrame))
|
||||
Window.Current.Content = rootFrame = new Frame();
|
||||
|
||||
if (e.PrelaunchActivated == false)
|
||||
{
|
||||
if (rootFrame.Content == null)
|
||||
rootFrame.Navigate(typeof(MainPage), e.Arguments);
|
||||
|
||||
Window.Current.Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 525 B |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 525 B |
|
After Width: | Height: | Size: 766 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 12 KiB |