Adding final project to dev branch
This commit is contained in:
3
WguApp/.gitignore
vendored
Normal file
3
WguApp/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
bin/
|
||||
obj/
|
||||
.idea/
|
||||
0
WguApp/.noai
Normal file
0
WguApp/.noai
Normal file
14
WguApp/App.xaml
Normal file
14
WguApp/App.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:WguApp"
|
||||
x:Class="WguApp.App">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
25
WguApp/App.xaml.cs
Normal file
25
WguApp/App.xaml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using WguApp.Services;
|
||||
using WguApp.Views;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
|
||||
private HomePage _homePage = new();
|
||||
private NavigationPage _navPage;
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if (Current != null) Current.UserAppTheme = AppTheme.Dark;
|
||||
|
||||
_navPage = new NavigationPage(_homePage);
|
||||
}
|
||||
|
||||
protected override Window CreateWindow(IActivationState? activationState)
|
||||
{
|
||||
return new Window(_navPage);
|
||||
}
|
||||
}
|
||||
29
WguApp/Controls/CustomButton.xaml
Normal file
29
WguApp/Controls/CustomButton.xaml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Controls.CustomButton"
|
||||
x:Name="ThisControl">
|
||||
<Border>
|
||||
<Grid BackgroundColor="#002f51"
|
||||
Padding="10"
|
||||
ColumnDefinitions="*, Auto">
|
||||
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" NumberOfTapsRequired="1" />
|
||||
</Grid.GestureRecognizers>
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="{Binding Text, Source={x:Reference ThisControl}}"
|
||||
FontSize="15"
|
||||
VerticalOptions="Center"
|
||||
TextColor="AliceBlue"
|
||||
HorizontalOptions="Start"/>
|
||||
|
||||
<Label Grid.Column="1"
|
||||
Text="{Binding DateText, Source={x:Reference ThisControl}}"
|
||||
FontSize="12"
|
||||
VerticalOptions="Center"
|
||||
TextColor="Gray"
|
||||
Margin="10,0,0,0"/> </Grid>
|
||||
</Border>
|
||||
</ContentView>
|
||||
51
WguApp/Controls/CustomButton.xaml.cs
Normal file
51
WguApp/Controls/CustomButton.xaml.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WguApp.Controls;
|
||||
|
||||
public partial class CustomButton : ContentView
|
||||
{
|
||||
|
||||
public event EventHandler? Clicked;
|
||||
|
||||
public static readonly BindableProperty TextProperty =
|
||||
BindableProperty.Create(
|
||||
propertyName: nameof(Text),
|
||||
returnType: typeof(string),
|
||||
declaringType: typeof(CustomButton),
|
||||
defaultValue: "Text",
|
||||
defaultBindingMode: BindingMode.OneWay);
|
||||
|
||||
public static readonly BindableProperty DateTextProperty =
|
||||
BindableProperty.Create(
|
||||
propertyName: nameof(DateText),
|
||||
returnType: typeof(string),
|
||||
declaringType: typeof(CustomButton),
|
||||
defaultValue: "//",
|
||||
defaultBindingMode: BindingMode.OneWay);
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public string DateText
|
||||
{
|
||||
get => (string)GetValue(DateTextProperty);
|
||||
set => SetValue(DateTextProperty, value);
|
||||
}
|
||||
|
||||
public CustomButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void TapGestureRecognizer_OnTapped(object? sender, TappedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
2
WguApp/GlobalXmlns.cs
Normal file
2
WguApp/GlobalXmlns.cs
Normal file
@@ -0,0 +1,2 @@
|
||||
[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/maui/global", "WguApp")]
|
||||
[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/maui/global", "WguApp.Pages")]
|
||||
28
WguApp/MauiProgram.cs
Normal file
28
WguApp/MauiProgram.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Plugin.LocalNotification;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
public static class MauiProgram
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
|
||||
fonts.AddFont("Phosphor.ttf", "Phosphor");
|
||||
fonts.AddFont("Phosphor-Fill.ttf", "Phosphor-Fill");
|
||||
})
|
||||
.UseLocalNotification();
|
||||
|
||||
#if DEBUG
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
25
WguApp/Models/Assessment.cs
Normal file
25
WguApp/Models/Assessment.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using SQLite;
|
||||
|
||||
namespace WguApp.Models;
|
||||
|
||||
[Table("Assessments")]
|
||||
public class Assessment
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public int Id { get; set; }
|
||||
public int CourseId { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public AssessmentType Type { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public bool StartNotifCheck { get; set; } = false;
|
||||
public int StartNotifId { get; set; }
|
||||
public bool EndNotifCheck { get; set; } = false;
|
||||
public int EndNotifId { get; set; }
|
||||
}
|
||||
|
||||
public enum AssessmentType
|
||||
{
|
||||
Performance, Objective
|
||||
}
|
||||
42
WguApp/Models/Course.cs
Normal file
42
WguApp/Models/Course.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using SQLite;
|
||||
|
||||
namespace WguApp.Models;
|
||||
|
||||
[SQLite.Table("Courses")]
|
||||
public class Course
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public int Id { get; set; }
|
||||
public int TermId { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public CourseStatus Status { get; set; }
|
||||
public string InstructorName { get; set; } = string.Empty;
|
||||
public string InstructorPhone { get; set; } = string.Empty;
|
||||
public string InstructorEmail { get; set; } = string.Empty;
|
||||
public bool StartNotifCheck { get; set; } = false;
|
||||
public int StartNotifId { get; set; }
|
||||
public bool EndNotifCheck { get; set; } = false;
|
||||
public int EndNotifId { get; set; }
|
||||
public string Notes { get; set; } = string.Empty;
|
||||
|
||||
public Course() { }
|
||||
public Course(int termId, string name, DateTime startDate, DateTime endDate, CourseStatus status, string instructorName, string instructorPhone, string instructorEmail)
|
||||
{
|
||||
TermId = termId;
|
||||
Name = name;
|
||||
StartDate = startDate;
|
||||
EndDate = endDate;
|
||||
Status = status;
|
||||
InstructorName = instructorName;
|
||||
InstructorPhone = instructorPhone;
|
||||
InstructorEmail = instructorEmail;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CourseStatus
|
||||
{
|
||||
InProgress, Completed, Dropped, Planned
|
||||
}
|
||||
22
WguApp/Models/Term.cs
Normal file
22
WguApp/Models/Term.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using SQLite;
|
||||
|
||||
namespace WguApp.Models;
|
||||
|
||||
[Table("Terms")]
|
||||
public class Term
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public DateTime StartDate {get; set;}
|
||||
public DateTime EndDate {get; set;}
|
||||
|
||||
|
||||
public Term() { }
|
||||
public Term(string name, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
Name = name;
|
||||
StartDate = startDate;
|
||||
EndDate = endDate;
|
||||
}
|
||||
}
|
||||
15
WguApp/Platforms/Android/AndroidManifest.xml
Normal file
15
WguApp/Platforms/Android/AndroidManifest.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<!-- Optional: For exact timing -->
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" />
|
||||
</manifest>
|
||||
12
WguApp/Platforms/Android/MainActivity.cs
Normal file
12
WguApp/Platforms/Android/MainActivity.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop,
|
||||
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode |
|
||||
ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||
public class MainActivity : MauiAppCompatActivity
|
||||
{
|
||||
}
|
||||
15
WguApp/Platforms/Android/MainApplication.cs
Normal file
15
WguApp/Platforms/Android/MainApplication.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Android.App;
|
||||
using Android.Runtime;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
[Application]
|
||||
public class MainApplication : MauiApplication
|
||||
{
|
||||
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||
: base(handle, ownership)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
6
WguApp/Platforms/Android/Resources/values/colors.xml
Normal file
6
WguApp/Platforms/Android/Resources/values/colors.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#512BD4</color>
|
||||
<color name="colorPrimaryDark">#2B0B98</color>
|
||||
<color name="colorAccent">#2B0B98</color>
|
||||
</resources>
|
||||
9
WguApp/Platforms/MacCatalyst/AppDelegate.cs
Normal file
9
WguApp/Platforms/MacCatalyst/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Foundation;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
14
WguApp/Platforms/MacCatalyst/Entitlements.plist
Normal file
14
WguApp/Platforms/MacCatalyst/Entitlements.plist
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
|
||||
<dict>
|
||||
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
38
WguApp/Platforms/MacCatalyst/Info.plist
Normal file
38
WguApp/Platforms/MacCatalyst/Info.plist
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- The Mac App Store requires you specify if the app uses encryption. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
|
||||
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
|
||||
<!-- Please indicate <true/> or <false/> here. -->
|
||||
|
||||
<!-- Specify the category for your app here. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
|
||||
<!-- <key>LSApplicationCategoryType</key> -->
|
||||
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
15
WguApp/Platforms/MacCatalyst/Program.cs
Normal file
15
WguApp/Platforms/MacCatalyst/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
16
WguApp/Platforms/Tizen/Main.cs
Normal file
16
WguApp/Platforms/Tizen/Main.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
class Program : MauiApplication
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var app = new Program();
|
||||
app.Run(args);
|
||||
}
|
||||
}
|
||||
15
WguApp/Platforms/Tizen/tizen-manifest.xml
Normal file
15
WguApp/Platforms/Tizen/tizen-manifest.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="9" xmlns="http://tizen.org/ns/packages">
|
||||
<profile name="common" />
|
||||
<ui-application appid="maui-application-id-placeholder" exec="WguApp.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
|
||||
<label>maui-application-title-placeholder</label>
|
||||
<icon>maui-appicon-placeholder</icon>
|
||||
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
|
||||
</ui-application>
|
||||
<shortcut-list />
|
||||
<privileges>
|
||||
<privilege>http://tizen.org/privilege/internet</privilege>
|
||||
</privileges>
|
||||
<dependencies />
|
||||
<provides-appdefined-privileges />
|
||||
</manifest>
|
||||
8
WguApp/Platforms/Windows/App.xaml
Normal file
8
WguApp/Platforms/Windows/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<maui:MauiWinUIApplication
|
||||
x:Class="WguApp.WinUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:maui="using:Microsoft.Maui"
|
||||
xmlns:local="using:WguApp.WinUI">
|
||||
|
||||
</maui:MauiWinUIApplication>
|
||||
23
WguApp/Platforms/Windows/App.xaml.cs
Normal file
23
WguApp/Platforms/Windows/App.xaml.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace WguApp.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : MauiWinUIApplication
|
||||
{
|
||||
/// <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()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
46
WguApp/Platforms/Windows/Package.appxmanifest
Normal file
46
WguApp/Platforms/Windows/Package.appxmanifest
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="55663ABF-8FF6-41C6-A96E-913924D6F7A4" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>$placeholder$</DisplayName>
|
||||
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||
<Logo>$placeholder$.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="$placeholder$"
|
||||
Description="$placeholder$"
|
||||
Square150x150Logo="$placeholder$.png"
|
||||
Square44x44Logo="$placeholder$.png"
|
||||
BackgroundColor="transparent">
|
||||
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||
<uap:SplashScreen Image="$placeholder$.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
|
||||
</Package>
|
||||
15
WguApp/Platforms/Windows/app.manifest
Normal file
15
WguApp/Platforms/Windows/app.manifest
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="WguApp.WinUI.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
9
WguApp/Platforms/iOS/AppDelegate.cs
Normal file
9
WguApp/Platforms/iOS/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Foundation;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
32
WguApp/Platforms/iOS/Info.plist
Normal file
32
WguApp/Platforms/iOS/Info.plist
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
15
WguApp/Platforms/iOS/Program.cs
Normal file
15
WguApp/Platforms/iOS/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace WguApp;
|
||||
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
51
WguApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
Normal file
51
WguApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps.
|
||||
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK.
|
||||
|
||||
You are responsible for adding extra entries as needed for your application.
|
||||
|
||||
More information: https://aka.ms/maui-privacy-manifest
|
||||
-->
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>E174.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<!--
|
||||
The entry below is only needed when you're using the Preferences API in your app.
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict> -->
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
8
WguApp/Properties/launchSettings.json
Normal file
8
WguApp/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Windows Machine": {
|
||||
"commandName": "Project",
|
||||
"nativeDebugging": false
|
||||
}
|
||||
}
|
||||
}
|
||||
4
WguApp/Resources/AppIcon/appicon.svg
Normal file
4
WguApp/Resources/AppIcon/appicon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
8
WguApp/Resources/AppIcon/appiconfg.svg
Normal file
8
WguApp/Resources/AppIcon/appiconfg.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
WguApp/Resources/Fonts/OpenSans-Regular.ttf
Normal file
BIN
WguApp/Resources/Fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
BIN
WguApp/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
BIN
WguApp/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
Binary file not shown.
BIN
WguApp/Resources/Fonts/Phosphor-Fill.ttf
Normal file
BIN
WguApp/Resources/Fonts/Phosphor-Fill.ttf
Normal file
Binary file not shown.
BIN
WguApp/Resources/Fonts/Phosphor.ttf
Normal file
BIN
WguApp/Resources/Fonts/Phosphor.ttf
Normal file
Binary file not shown.
BIN
WguApp/Resources/Images/dotnet_bot.png
Normal file
BIN
WguApp/Resources/Images/dotnet_bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
15
WguApp/Resources/Raw/AboutAssets.txt
Normal file
15
WguApp/Resources/Raw/AboutAssets.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories). Deployment of the asset to your application
|
||||
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
|
||||
These files will be deployed with your package and will be accessible using Essentials:
|
||||
|
||||
async Task LoadMauiAsset()
|
||||
{
|
||||
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var contents = reader.ReadToEnd();
|
||||
}
|
||||
8
WguApp/Resources/Splash/splash.svg
Normal file
8
WguApp/Resources/Splash/splash.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
45
WguApp/Resources/Styles/Colors.xaml
Normal file
45
WguApp/Resources/Styles/Colors.xaml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
|
||||
|
||||
<Color x:Key="Primary">#512BD4</Color>
|
||||
<Color x:Key="PrimaryDark">#ac99ea</Color>
|
||||
<Color x:Key="PrimaryDarkText">#242424</Color>
|
||||
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||
<Color x:Key="SecondaryDarkText">#9880e5</Color>
|
||||
<Color x:Key="Tertiary">#2B0B98</Color>
|
||||
|
||||
<Color x:Key="White">White</Color>
|
||||
<Color x:Key="Black">Black</Color>
|
||||
<Color x:Key="Magenta">#D600AA</Color>
|
||||
<Color x:Key="MidnightBlue">#190649</Color>
|
||||
<Color x:Key="OffBlack">#1f1f1f</Color>
|
||||
|
||||
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||
<Color x:Key="Gray300">#ACACAC</Color>
|
||||
<Color x:Key="Gray400">#919191</Color>
|
||||
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||
<Color x:Key="Gray600">#404040</Color>
|
||||
<Color x:Key="Gray900">#212121</Color>
|
||||
<Color x:Key="Gray950">#141414</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||
|
||||
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||
</ResourceDictionary>
|
||||
440
WguApp/Resources/Styles/Styles.xaml
Normal file
440
WguApp/Resources/Styles/Styles.xaml
Normal file
@@ -0,0 +1,440 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<Style TargetType="ActivityIndicator">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="IndicatorView">
|
||||
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||
<Setter Property="StrokeThickness" Value="1"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BoxView">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
<Setter Property="Padding" Value="14,10"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="DatePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Editor">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Entry">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ImageButton">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
<Setter Property="BorderColor" Value="Transparent"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="Headline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="32" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="SubHeadline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Picker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RefreshView">
|
||||
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchBar">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchHandler">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shadow">
|
||||
<Setter Property="Radius" Value="15" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Offset" Value="10,10" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Slider">
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SwipeItem">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Switch">
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="On">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Off">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TimePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
<Style TargetType="TitleBar">
|
||||
<Setter Property="MinimumHeightRequest" Value="32"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="TitleActiveStates">
|
||||
<VisualState x:Name="TitleBarTitleActive">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="TitleBarTitleInactive">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
-->
|
||||
|
||||
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="NavigationPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TabbedPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
230
WguApp/Services/DatabaseService.cs
Normal file
230
WguApp/Services/DatabaseService.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
|
||||
using SQLite;
|
||||
using WguApp.Models;
|
||||
|
||||
namespace WguApp.Services;
|
||||
|
||||
public static class DatabaseService
|
||||
{
|
||||
|
||||
private static SQLiteAsyncConnection? _db;
|
||||
|
||||
public static async Task Init()
|
||||
{
|
||||
if (_db is not null) return;
|
||||
|
||||
var databasePath = Path.Combine(FileSystem.AppDataDirectory, "WguApp.db");
|
||||
_db = new SQLiteAsyncConnection(databasePath);
|
||||
|
||||
try
|
||||
{
|
||||
await _db.CreateTablesAsync<Term, Course, Assessment>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// -- Add Methods -- //
|
||||
#region Add methods
|
||||
|
||||
public static async Task<bool> AddTerm(Term term)
|
||||
{
|
||||
await Init();
|
||||
var result = await _db?.InsertAsync(term)!;
|
||||
return !(result <= 0);
|
||||
}
|
||||
|
||||
public static async Task<bool> AddCourse(Course course)
|
||||
{
|
||||
await Init();
|
||||
var result = await _db?.InsertAsync(course)!;
|
||||
return !(result <= 0);
|
||||
}
|
||||
|
||||
public static async Task<bool> AddAssessment(Assessment assessment)
|
||||
{
|
||||
await Init();
|
||||
var result = await _db?.InsertAsync(assessment)!;
|
||||
return !(result <= 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// -- Get Methods -- //
|
||||
#region Get Methods
|
||||
public static async Task<List<Term>> GetAllTerms()
|
||||
{
|
||||
await Init();
|
||||
var allTerms = await _db?.Table<Term>().ToListAsync()!;
|
||||
return allTerms ?? [];
|
||||
}
|
||||
|
||||
public static async Task<List<Course>> GetAllCourses()
|
||||
{
|
||||
await Init();
|
||||
var allCourses = await _db?.Table<Course>().ToListAsync()!;
|
||||
return allCourses ?? [];
|
||||
}
|
||||
|
||||
public static async Task<List<Assessment>> GetAllAssessments()
|
||||
{
|
||||
await Init();
|
||||
var allAssessments = await _db?.Table<Assessment>().ToListAsync()!;
|
||||
return allAssessments ?? [];
|
||||
}
|
||||
|
||||
public static async Task<List<Assessment>> GetAssessmentsByCourseId(int courseId)
|
||||
{
|
||||
await Init();
|
||||
var query = $"SELECT * FROM Assessments WHERE CourseId = {courseId}";
|
||||
var result = await _db?.QueryAsync<Assessment>(query)!;
|
||||
return result.ToList() ?? [];
|
||||
}
|
||||
|
||||
public static async Task<List<Course>> GetCoursesByTermId(int termId)
|
||||
{
|
||||
await Init();
|
||||
var query = $"SELECT * FROM Courses WHERE TermId = {termId}";
|
||||
var result = await _db?.QueryAsync<Course>(query)!;
|
||||
return result.ToList() ?? [];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// -- Update Methods
|
||||
#region Update Methods
|
||||
|
||||
public static async Task<bool> UpdateTerm(Term term)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.UpdateAsync(term)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> UpdateCourse(Course course)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.UpdateAsync(course)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> UpdateAssessment(Assessment assessment)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.UpdateAsync(assessment)! != 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// -- Delete Methods
|
||||
#region Delete Methods
|
||||
public static async Task<bool> DeleteTerm(Term term)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync(term)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteTerm(int termId)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync<Term>(termId)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteCourse(Course course)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync(course)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteCourse(int courseId)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync<Course>(courseId)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteAssessment(Assessment assessment)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync(assessment)! != 0;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteAssessment(int assessmentId)
|
||||
{
|
||||
await Init();
|
||||
return await _db?.DeleteAsync<Assessment>(assessmentId)! != 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
// -- Sample Data -- //
|
||||
public static async Task LoadSampleData()
|
||||
{
|
||||
await ClearDbData();
|
||||
|
||||
var term1 = new Term()
|
||||
{
|
||||
Name = "Term 1",
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30)
|
||||
};
|
||||
|
||||
await AddTerm(term1);
|
||||
|
||||
var course1 = new Course()
|
||||
{
|
||||
TermId = term1.Id,
|
||||
Name = "Course 1",
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30),
|
||||
InstructorName = "Anika Patel",
|
||||
InstructorEmail = "anika.patel@strimeuniversity.edu",
|
||||
InstructorPhone = "555-123-4567",
|
||||
StartNotifCheck = false,
|
||||
EndNotifCheck = false,
|
||||
Status = CourseStatus.InProgress,
|
||||
Notes = "Some notes"
|
||||
};
|
||||
|
||||
await AddCourse(course1);
|
||||
|
||||
var assessment1 = new Assessment()
|
||||
{
|
||||
CourseId = course1.Id,
|
||||
Name = "Performance Assessment",
|
||||
Type = AssessmentType.Performance,
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30),
|
||||
StartNotifCheck = false,
|
||||
EndNotifCheck = false
|
||||
};
|
||||
|
||||
await AddAssessment(assessment1);
|
||||
|
||||
var assessment2 = new Assessment()
|
||||
{
|
||||
CourseId = course1.Id,
|
||||
Name = "Objective Assessment",
|
||||
Type = AssessmentType.Objective,
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30),
|
||||
StartNotifCheck = false,
|
||||
EndNotifCheck = false
|
||||
};
|
||||
|
||||
await AddAssessment(assessment2);
|
||||
}
|
||||
|
||||
public static async Task ClearDbData()
|
||||
{
|
||||
await Init();
|
||||
|
||||
await _db?.DeleteAllAsync<Assessment>()!;
|
||||
await _db?.DeleteAllAsync<Course>()!;
|
||||
await _db?.DeleteAllAsync<Term>()!;
|
||||
|
||||
_db = null;
|
||||
|
||||
}
|
||||
}
|
||||
114
WguApp/Services/LocalNotificationService.cs
Normal file
114
WguApp/Services/LocalNotificationService.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Plugin.LocalNotification;
|
||||
|
||||
namespace WguApp.Services;
|
||||
|
||||
public static class LocalNotificationService
|
||||
{
|
||||
private static readonly Random Rng = new();
|
||||
|
||||
public static async Task<int?> ScheduleNotification(string title, string description, DateTime time)
|
||||
{
|
||||
var permCheck = await PermissionsService.CheckNotificationPermissions();
|
||||
if (!permCheck)
|
||||
{
|
||||
LoggerService.LogToFile("Notification Service: Notification Permission Not Granted");
|
||||
return null;
|
||||
}
|
||||
|
||||
var newId = Rng.Next();
|
||||
|
||||
var notif = new NotificationRequest
|
||||
{
|
||||
NotificationId = newId,
|
||||
Title = title,
|
||||
Description = description,
|
||||
Schedule =
|
||||
{
|
||||
NotifyTime = time,
|
||||
RepeatType = NotificationRepeat.No
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await LocalNotificationCenter.Current.Show(notif);
|
||||
LoggerService.LogToFile($"Notification Service: {notif.NotificationId}:{notif.Title} set");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LoggerService.LogToFile($"Notification Service: {e.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
return notif.NotificationId;
|
||||
}
|
||||
|
||||
public static async Task<int> ScheduleNotification(NotificationRequest notif)
|
||||
{
|
||||
try
|
||||
{
|
||||
await LocalNotificationCenter.Current.Show(notif);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LoggerService.LogToFile(e.Message);
|
||||
throw;
|
||||
}
|
||||
return notif.NotificationId;
|
||||
}
|
||||
|
||||
public static async Task<bool> UpdateNotification(int notificationId, string? title = null, string? description = null, DateTime? time = null)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
|
||||
var notif = pendingNotifs.FirstOrDefault(n => n.NotificationId == notificationId);
|
||||
|
||||
if (notif is null) return false;
|
||||
|
||||
await CancelNotification(notif);
|
||||
|
||||
notif.Title = title ?? notif.Title;
|
||||
notif.Description = description ?? notif.Description;
|
||||
notif.Schedule = new NotificationRequestSchedule()
|
||||
{
|
||||
NotifyTime = time ?? notif.Schedule.NotifyTime,
|
||||
RepeatType = NotificationRepeat.No
|
||||
};
|
||||
|
||||
await ScheduleNotification(notif);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> CancelNotification(int notificationId)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
|
||||
var match = pendingNotifs.FirstOrDefault(n => n.NotificationId == notificationId);
|
||||
|
||||
if (match is null) return false;
|
||||
|
||||
LocalNotificationCenter.Current.Cancel(notificationId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> CancelNotification(NotificationRequest notif)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
|
||||
if (pendingNotifs.Contains(notif))
|
||||
{
|
||||
notif.Cancel();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> DoesNotificationAlreadyExist(int notificationId)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
var match = pendingNotifs.FirstOrDefault(n => n.NotificationId == notificationId);
|
||||
|
||||
return match is not null;
|
||||
}
|
||||
}
|
||||
11
WguApp/Services/LoggerService.cs
Normal file
11
WguApp/Services/LoggerService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace WguApp.Services;
|
||||
|
||||
public class LoggerService
|
||||
{
|
||||
public static void LogToFile(string text)
|
||||
{
|
||||
var logFilePath = Path.Combine(FileSystem.AppDataDirectory, "log.txt");
|
||||
|
||||
File.AppendAllText(logFilePath, $"{DateTime.UtcNow} : {text}\n");
|
||||
}
|
||||
}
|
||||
21
WguApp/Services/PermissionsService.cs
Normal file
21
WguApp/Services/PermissionsService.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Plugin.LocalNotification;
|
||||
|
||||
namespace WguApp.Services;
|
||||
|
||||
public static class PermissionsService
|
||||
{
|
||||
public static async Task<bool> CheckNotificationPermissions()
|
||||
{
|
||||
if (await LocalNotificationCenter.Current.AreNotificationsEnabled()) return true;
|
||||
|
||||
try
|
||||
{
|
||||
return await LocalNotificationCenter.Current.RequestNotificationPermission();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LoggerService.LogToFile(e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
WguApp/Views/AssessmentPage.xaml
Normal file
125
WguApp/Views/AssessmentPage.xaml
Normal file
@@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Views.AssessmentPage">
|
||||
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Save"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=AliceBlue}"
|
||||
Clicked="SaveButton_OnClicked"/>
|
||||
<ToolbarItem Text="Delete"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=Red}"
|
||||
Clicked="DeleteButton_OnClicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<Grid RowDefinitions="*">
|
||||
<ScrollView HorizontalOptions="Fill"
|
||||
HorizontalScrollBarVisibility="Never">
|
||||
<VerticalStackLayout HorizontalOptions="Fill">
|
||||
|
||||
<Label Text="Assessment Info"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 10, 20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Title:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<Entry x:Name="TitleEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Enter value here..."
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Start date:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<DatePicker x:Name="StartDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Expected end date:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<DatePicker x:Name="EndDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Label Text="Notifications"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Start Date:"
|
||||
VerticalOptions="Center" />
|
||||
<CheckBox x:Name="StartNotifCheck"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="End Date:"
|
||||
VerticalOptions="Center" />
|
||||
<CheckBox x:Name="EndNotifCheck"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
137
WguApp/Views/AssessmentPage.xaml.cs
Normal file
137
WguApp/Views/AssessmentPage.xaml.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WguApp.Models;
|
||||
using WguApp.Services;
|
||||
|
||||
namespace WguApp.Views;
|
||||
|
||||
public partial class AssessmentPage : ContentPage
|
||||
{
|
||||
|
||||
private Assessment _assessment;
|
||||
|
||||
public AssessmentPage(Assessment assessment)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_assessment = assessment;
|
||||
|
||||
Title = assessment.Name;
|
||||
|
||||
TitleEntry.Text = _assessment.Name;
|
||||
StartDatePicker.Date = _assessment.StartDate;
|
||||
EndDatePicker.Date = _assessment.EndDate;
|
||||
StartNotifCheck.IsChecked = _assessment.StartNotifCheck;
|
||||
EndNotifCheck.IsChecked = _assessment.EndNotifCheck;
|
||||
|
||||
StartNotifCheck.CheckedChanged += async (sender, e) => { await ToggleStartNotification(); };
|
||||
EndNotifCheck.CheckedChanged += async (sender, e) => { await ToggleEndNotification(); };
|
||||
}
|
||||
|
||||
private async Task ToggleStartNotification()
|
||||
{
|
||||
if (StartNotifCheck.IsChecked)
|
||||
{
|
||||
var id = await LocalNotificationService.ScheduleNotification($"{_assessment.Name} Start Reminder", $"Your assessment '{_assessment.Id} starts in 12 hours'", _assessment.StartDate.Subtract(TimeSpan.FromHours(12)));
|
||||
_assessment.StartNotifId = id ?? 0;
|
||||
LoggerService.LogToFile($"{_assessment.Id}:{_assessment.Name} set start notification {_assessment.StartNotifId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = await LocalNotificationService.CancelNotification(_assessment.StartNotifId);
|
||||
LoggerService.LogToFile($"{_assessment.Id}:{_assessment.Name} canceled start notification {_assessment.StartNotifId}");
|
||||
_assessment.StartNotifId = 0;
|
||||
}
|
||||
|
||||
_assessment.StartNotifCheck = StartNotifCheck.IsChecked;
|
||||
}
|
||||
|
||||
private async Task ToggleEndNotification()
|
||||
{
|
||||
if (EndNotifCheck.IsChecked)
|
||||
{
|
||||
var id = await LocalNotificationService.ScheduleNotification($"{_assessment.Name} End Reminder", $"Your assessment '{_assessment.Id} ends in 12 hours'", _assessment.EndDate.Subtract(TimeSpan.FromHours(12)));
|
||||
_assessment.EndNotifId = id ?? 0;
|
||||
LoggerService.LogToFile($"{_assessment.Id}:{_assessment.Name} set end notification {_assessment.EndNotifId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = await LocalNotificationService.CancelNotification(_assessment.EndNotifId);
|
||||
LoggerService.LogToFile($"{_assessment.Id}:{_assessment.Name} canceled end notification {_assessment.EndNotifId}");
|
||||
_assessment.EndNotifId = 0;
|
||||
}
|
||||
|
||||
_assessment.EndNotifCheck = EndNotifCheck.IsChecked;
|
||||
}
|
||||
|
||||
private (string msg, bool result) ValidateFields()
|
||||
{
|
||||
var message = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(TitleEntry.Text)) message += "Title cannot be blank\n";
|
||||
if (StartDatePicker.Date > EndDatePicker.Date) message += "Start Date cannot be after the End Date\n";
|
||||
|
||||
return string.IsNullOrWhiteSpace(message) ? (message, true) : (message, false);
|
||||
}
|
||||
|
||||
private async Task<bool> Save()
|
||||
{
|
||||
var validationResult = ValidateFields();
|
||||
|
||||
if (!validationResult.result)
|
||||
{
|
||||
await DisplayAlert("Validation Error", validationResult.msg, "Ok");
|
||||
return false;
|
||||
}
|
||||
|
||||
_assessment.Name = TitleEntry.Text;
|
||||
_assessment.StartDate = StartDatePicker.Date;
|
||||
_assessment.EndDate = EndDatePicker.Date;
|
||||
_assessment.StartNotifCheck = StartNotifCheck.IsChecked;
|
||||
_assessment.EndNotifCheck = EndNotifCheck.IsChecked;
|
||||
|
||||
var updateResult = await DatabaseService.UpdateAssessment(_assessment);
|
||||
|
||||
if (updateResult)
|
||||
{
|
||||
await DisplayAlert("Info", $"{_assessment.Name} Saved!", "Ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
await DisplayAlert("Error", "Could not save term", "Ok");
|
||||
}
|
||||
|
||||
Title = _assessment.Name;
|
||||
|
||||
if (_assessment.StartNotifId != 0)
|
||||
{
|
||||
await LocalNotificationService.UpdateNotification(_assessment.StartNotifId, $"{_assessment.Name} Start Reminder",
|
||||
$"Your course '{_assessment.Id} starts in 12 hours'", _assessment.StartDate.Subtract(TimeSpan.FromHours(12)));
|
||||
}
|
||||
|
||||
if (_assessment.EndNotifId != 0)
|
||||
{
|
||||
await LocalNotificationService.UpdateNotification(_assessment.EndNotifId, $"{_assessment.Name} End Reminder",
|
||||
$"Your course '{_assessment.Id} ends in 12 hours'", _assessment.EndDate.Subtract(TimeSpan.FromHours(12)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void SaveButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
await Save();
|
||||
}
|
||||
|
||||
private async void DeleteButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var result = await DisplayAlert("Delete Course", $"Do you really want to delete '{_assessment.Name}'? This action cannot be undone.", "Delete", "Cancel");
|
||||
if (!result) return;
|
||||
|
||||
await DatabaseService.DeleteAssessment(_assessment);
|
||||
await Navigation.PopAsync();
|
||||
}
|
||||
}
|
||||
270
WguApp/Views/CoursePage.xaml
Normal file
270
WguApp/Views/CoursePage.xaml
Normal file
@@ -0,0 +1,270 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Views.CoursePage">
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Save"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=AliceBlue}"
|
||||
Clicked="SaveButton_OnClicked"/>
|
||||
<ToolbarItem Text="Delete"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=Red}"
|
||||
Clicked="DeleteButton_OnClicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<Grid RowDefinitions="*">
|
||||
<ScrollView HorizontalOptions="Fill"
|
||||
HorizontalScrollBarVisibility="Never">
|
||||
<VerticalStackLayout HorizontalOptions="Fill">
|
||||
<Label Text="Course Info"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 10, 20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Title:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<Entry x:Name="TitleEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Enter value here..."
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Start date:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<DatePicker x:Name="StartDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Expected end date:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<DatePicker x:Name="EndDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Status:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<Picker x:Name="StatusPicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Label Text="Instructor"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 10, 20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Name:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<Entry x:Name="InstructorNameEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Name"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10, 20, 5">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Phone:"
|
||||
VerticalOptions="Center" />
|
||||
|
||||
<Entry x:Name="InstructorPhoneEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Phone"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Email:"
|
||||
VerticalOptions="Center" />
|
||||
<Entry x:Name="InstructorEmailEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Email"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 5">
|
||||
|
||||
<Label Grid.Column="0" Text="Notes"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
VerticalOptions="Center"/>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
Text=""
|
||||
FontFamily="Phosphor"
|
||||
FontSize="20"
|
||||
WidthRequest="20"
|
||||
HeightRequest="20"
|
||||
TextColor="AliceBlue"
|
||||
BackgroundColor="Transparent"
|
||||
HorizontalOptions="End"
|
||||
VerticalOptions="Center"
|
||||
Clicked="ShareNotesButton_OnClicked"/>
|
||||
</Grid>
|
||||
|
||||
<Border HorizontalOptions="Fill"
|
||||
Margin="30, 5"
|
||||
Stroke="AliceBlue"
|
||||
StrokeThickness="2">
|
||||
<Editor x:Name="NotesEditor"
|
||||
HeightRequest="150"/>
|
||||
</Border>
|
||||
|
||||
<Label Text="Notifications"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Start Date:"
|
||||
VerticalOptions="Center" />
|
||||
<CheckBox x:Name="StartNotifCheck"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, Auto"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="End Date:"
|
||||
VerticalOptions="Center" />
|
||||
<CheckBox x:Name="EndNotifCheck"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="End" />
|
||||
</Grid>
|
||||
|
||||
<Grid RowDefinitions="*, Auto"
|
||||
ColumnDefinitions="*, Auto"
|
||||
HorizontalOptions="Fill"
|
||||
HeightRequest="40"
|
||||
Margin="30, 20, 30, 0">
|
||||
|
||||
<Label Text="Assessments"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontSize="15"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Fill"
|
||||
HorizontalTextAlignment="Start"
|
||||
HeightRequest="20" />
|
||||
|
||||
<Button Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Text=""
|
||||
FontFamily="Phosphor"
|
||||
FontSize="15"
|
||||
WidthRequest="20"
|
||||
HeightRequest="20"
|
||||
TextColor="AliceBlue"
|
||||
BackgroundColor="Transparent"
|
||||
HorizontalOptions="End"
|
||||
VerticalOptions="Center"
|
||||
Clicked="AddAssessmentButton_OnClicked"/>
|
||||
</Grid>
|
||||
|
||||
<BoxView
|
||||
Color="AliceBlue"
|
||||
HeightRequest="2"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="30, 0, 30, 20" />
|
||||
|
||||
<VerticalStackLayout x:Name="AssessmentButtonStack"
|
||||
Margin="30,10"
|
||||
HorizontalOptions="Fill"
|
||||
Spacing="5"/>
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
264
WguApp/Views/CoursePage.xaml.cs
Normal file
264
WguApp/Views/CoursePage.xaml.cs
Normal file
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WguApp.Controls;
|
||||
using WguApp.Models;
|
||||
using WguApp.Services;
|
||||
|
||||
namespace WguApp.Views;
|
||||
|
||||
public partial class CoursePage : ContentPage
|
||||
{
|
||||
|
||||
private Course _course;
|
||||
|
||||
private Assessment? _oa = null;
|
||||
private Assessment? _pa = null;
|
||||
|
||||
public CoursePage(Course course)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_course = course;
|
||||
|
||||
Title = _course.Name;
|
||||
|
||||
StatusPicker.ItemsSource = Enum.GetValues<CourseStatus>();
|
||||
|
||||
TitleEntry.Text = _course.Name;
|
||||
StartDatePicker.Date = _course.StartDate;
|
||||
EndDatePicker.Date = _course.EndDate;
|
||||
StatusPicker.SelectedItem = _course.Status;
|
||||
InstructorNameEntry.Text = _course.InstructorName;
|
||||
InstructorEmailEntry.Text = _course.InstructorEmail;
|
||||
InstructorPhoneEntry.Text = _course.InstructorPhone;
|
||||
NotesEditor.Text = _course.Notes;
|
||||
StartNotifCheck.IsChecked = _course.StartNotifCheck;
|
||||
EndNotifCheck.IsChecked = _course.EndNotifCheck;
|
||||
|
||||
StartNotifCheck.CheckedChanged += async (sender, e) => { await ToggleStartNotification(); };
|
||||
EndNotifCheck.CheckedChanged += async (sender, e) => { await ToggleEndNotification(); };
|
||||
}
|
||||
|
||||
private async Task ToggleStartNotification()
|
||||
{
|
||||
if (StartNotifCheck.IsChecked)
|
||||
{
|
||||
var id = await LocalNotificationService.ScheduleNotification($"{_course.Name} Start Reminder", $"Your course '{_course.Id} starts in 12 hours'", _course.StartDate.Subtract(TimeSpan.FromHours(12)));
|
||||
_course.StartNotifId = id ?? 0;
|
||||
LoggerService.LogToFile($"{_course.Id}:{_course.Name} set start notification {_course.StartNotifId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = await LocalNotificationService.CancelNotification(_course.StartNotifId);
|
||||
LoggerService.LogToFile($"{_course.Id}:{_course.Name} canceled start notification {_course.StartNotifId}");
|
||||
_course.StartNotifId = 0;
|
||||
}
|
||||
|
||||
_course.StartNotifCheck = StartNotifCheck.IsChecked;
|
||||
}
|
||||
|
||||
private async Task ToggleEndNotification()
|
||||
{
|
||||
if (EndNotifCheck.IsChecked)
|
||||
{
|
||||
var id = await LocalNotificationService.ScheduleNotification($"{_course.Name} End Reminder", $"Your course '{_course.Id} ends in 12 hours'", _course.EndDate.Subtract(TimeSpan.FromHours(12)));
|
||||
_course.EndNotifId = id ?? 0;
|
||||
LoggerService.LogToFile($"{_course.Id}:{_course.Name} set end notification {_course.EndNotifId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = await LocalNotificationService.CancelNotification(_course.EndNotifId);
|
||||
LoggerService.LogToFile($"{_course.Id}:{_course.Name} canceled end notification {_course.EndNotifId}");
|
||||
_course.EndNotifId = 0;
|
||||
}
|
||||
|
||||
_course.EndNotifCheck = EndNotifCheck.IsChecked;
|
||||
}
|
||||
|
||||
private (string msg, bool result) ValidateFields()
|
||||
{
|
||||
var message = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(TitleEntry.Text)) message += "Title cannot be blank\n";
|
||||
if (StartDatePicker.Date > EndDatePicker.Date) message += "Start Date cannot be after the End Date\n";
|
||||
if (string.IsNullOrWhiteSpace(InstructorNameEntry.Text)) message += "Instructor Name cannot be blank\n";
|
||||
if (string.IsNullOrWhiteSpace(InstructorPhoneEntry.Text)) message += "Instructor Phone cannot be blank\n";
|
||||
if (string.IsNullOrWhiteSpace(InstructorEmailEntry.Text)) message += "Instructor Email cannot be blank\n";
|
||||
|
||||
return string.IsNullOrWhiteSpace(message) ? (message, true) : (message, false);
|
||||
}
|
||||
|
||||
private async void SaveButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
await Save();
|
||||
}
|
||||
|
||||
private async Task<bool> Save()
|
||||
{
|
||||
var validationResult = ValidateFields();
|
||||
|
||||
if (!validationResult.result)
|
||||
{
|
||||
await DisplayAlert("Validation Error", validationResult.msg, "Ok");
|
||||
return false;
|
||||
}
|
||||
|
||||
_course.Name = TitleEntry.Text;
|
||||
_course.StartDate = StartDatePicker.Date;
|
||||
_course.EndDate = EndDatePicker.Date;
|
||||
_course.InstructorName = InstructorNameEntry.Text;
|
||||
_course.InstructorPhone = InstructorPhoneEntry.Text;
|
||||
_course.InstructorEmail = InstructorEmailEntry.Text;
|
||||
_course.Notes = NotesEditor.Text;
|
||||
_course.StartNotifCheck = StartNotifCheck.IsChecked;
|
||||
_course.EndNotifCheck = EndNotifCheck.IsChecked;
|
||||
|
||||
var updateResult = await DatabaseService.UpdateCourse(_course);
|
||||
|
||||
if (updateResult)
|
||||
{
|
||||
await DisplayAlert("Info", $"{_course.Name} Saved!", "Ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
await DisplayAlert("Error", "Could not save term", "Ok");
|
||||
}
|
||||
|
||||
Title = _course.Name;
|
||||
|
||||
if (_course.StartNotifId != 0)
|
||||
{
|
||||
await LocalNotificationService.UpdateNotification(_course.StartNotifId, $"{_course.Name} Start Reminder",
|
||||
$"Your course '{_course.Id} starts in 12 hours'", _course.StartDate.Subtract(TimeSpan.FromHours(12)));
|
||||
}
|
||||
|
||||
if (_course.EndNotifId != 0)
|
||||
{
|
||||
await LocalNotificationService.UpdateNotification(_course.EndNotifId, $"{_course.Name} End Reminder",
|
||||
$"Your course '{_course.Id} ends in 12 hours'", _course.EndDate.Subtract(TimeSpan.FromHours(12)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void DeleteButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var result = await DisplayAlert("Delete Course", $"Do you really want to delete '{_course.Name}'? This action cannot be undone.", "Delete", "Cancel");
|
||||
if (!result) return;
|
||||
|
||||
await DatabaseService.DeleteCourse(_course);
|
||||
await Navigation.PopAsync();
|
||||
}
|
||||
|
||||
private async void ShareNotesButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(NotesEditor.Text))
|
||||
{
|
||||
await DisplayAlert("Info", "Failed to share: Notes are empty", "Ok");
|
||||
}
|
||||
|
||||
await Share.Default.RequestAsync(new ShareTextRequest
|
||||
{
|
||||
Title = "Share course notes",
|
||||
Text = $"-- Course notes for {_course.Name} --\n{NotesEditor.Text}"
|
||||
});
|
||||
}
|
||||
|
||||
private async Task RefreshAssessmentsList()
|
||||
{
|
||||
AssessmentButtonStack.Children.Clear();
|
||||
|
||||
var allAssessments = await DatabaseService.GetAssessmentsByCourseId(_course.Id);
|
||||
|
||||
_oa = allAssessments.FirstOrDefault(a => a.Type == AssessmentType.Objective);
|
||||
_pa = allAssessments.FirstOrDefault(a => a.Type == AssessmentType.Performance);
|
||||
|
||||
if (_oa is not null)
|
||||
{
|
||||
var oaBtn = new CustomButton()
|
||||
{
|
||||
Text = _oa.Name,
|
||||
DateText = $"{DateOnly.FromDateTime(_oa.StartDate).ToString()} - {DateOnly.FromDateTime(_oa.EndDate).ToString()}"
|
||||
};
|
||||
|
||||
AssessmentButtonStack.Add(oaBtn);
|
||||
|
||||
oaBtn.Clicked += async (sender, e) => { await HandleAssessmentButtonClick(_oa); };
|
||||
}
|
||||
|
||||
if (_pa is not null)
|
||||
{
|
||||
var paBtn = new CustomButton()
|
||||
{
|
||||
Text = _pa.Name,
|
||||
DateText = $"{DateOnly.FromDateTime(_pa.StartDate).ToString()} - {DateOnly.FromDateTime(_pa.EndDate).ToString()}"
|
||||
};
|
||||
|
||||
AssessmentButtonStack.Add(paBtn);
|
||||
|
||||
paBtn.Clicked += async (sender, e) => { await HandleAssessmentButtonClick(_pa); };
|
||||
}
|
||||
}
|
||||
|
||||
protected async override void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
await RefreshAssessmentsList();
|
||||
}
|
||||
|
||||
private async Task HandleAssessmentButtonClick(Assessment assessment)
|
||||
{
|
||||
await Navigation.PushAsync(new AssessmentPage(assessment));
|
||||
}
|
||||
|
||||
private async void AddAssessmentButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (_oa is not null && _pa is not null)
|
||||
{
|
||||
await DisplayAlert("Info", "Cannot add any more assessments", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
var action = await DisplayActionSheet("Which type of lesson do you want to add?", "Cancel", null, "Performance",
|
||||
"Objective");
|
||||
|
||||
if (action is null or "Cancel") return;
|
||||
|
||||
var assessment = new Assessment
|
||||
{
|
||||
CourseId = _course.Id,
|
||||
StartDate = DateTime.Now,
|
||||
EndDate = DateTime.Today.AddDays(30),
|
||||
StartNotifCheck = false,
|
||||
EndNotifCheck = false
|
||||
};
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case "Objective":
|
||||
if (_oa is not null)
|
||||
{
|
||||
await DisplayAlert("Info", "Cannot add any more objective assessments", "Ok");
|
||||
break;
|
||||
}
|
||||
assessment.Type = AssessmentType.Objective;
|
||||
assessment.Name = "Objective Assessment";
|
||||
break;
|
||||
case "Performance":
|
||||
if (_pa is not null)
|
||||
{
|
||||
await DisplayAlert("Info", "Cannot add any more performance assessments", "Ok");
|
||||
break;
|
||||
}
|
||||
assessment.Type = AssessmentType.Performance;
|
||||
assessment.Name = "Performance Assessment";
|
||||
break;
|
||||
}
|
||||
|
||||
await DatabaseService.AddAssessment(assessment);
|
||||
|
||||
await RefreshAssessmentsList();
|
||||
}
|
||||
}
|
||||
66
WguApp/Views/HomePage.xaml
Normal file
66
WguApp/Views/HomePage.xaml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Views.HomePage"
|
||||
Title="Home">
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Add"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
Clicked="TestButton_OnClicked"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=24, Color=AliceBlue}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<Grid HorizontalOptions="Fill"
|
||||
Padding="30, 20"
|
||||
RowDefinitions="Auto, Auto, *, Auto">
|
||||
|
||||
<Grid RowDefinitions="*, Auto"
|
||||
ColumnDefinitions="*, Auto"
|
||||
HorizontalOptions="Fill"
|
||||
HeightRequest="40"
|
||||
Grid.Row="0">
|
||||
|
||||
<Label Text="Terms"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontSize="15"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Fill"
|
||||
HorizontalTextAlignment="Start"
|
||||
HeightRequest="20" />
|
||||
|
||||
<Button Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Text=""
|
||||
FontFamily="Phosphor"
|
||||
FontSize="15"
|
||||
WidthRequest="20"
|
||||
HeightRequest="20"
|
||||
TextColor="AliceBlue"
|
||||
BackgroundColor="Transparent"
|
||||
HorizontalOptions="End"
|
||||
VerticalOptions="Center"
|
||||
Clicked="AddTermButton_OnClicked"/>
|
||||
</Grid>
|
||||
|
||||
<BoxView
|
||||
Grid.Row="1"
|
||||
Color="AliceBlue"
|
||||
HeightRequest="2"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="0, 0, 0, 20" />
|
||||
|
||||
<ScrollView HorizontalOptions="Fill"
|
||||
HorizontalScrollBarVisibility="Never"
|
||||
Grid.Row="2">
|
||||
<VerticalStackLayout x:Name="TermButtonStack"
|
||||
Margin="0,10"
|
||||
HorizontalOptions="Fill"
|
||||
Spacing="5"/>
|
||||
</ScrollView>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
79
WguApp/Views/HomePage.xaml.cs
Normal file
79
WguApp/Views/HomePage.xaml.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WguApp.Controls;
|
||||
using WguApp.Models;
|
||||
using WguApp.Services;
|
||||
|
||||
namespace WguApp.Views;
|
||||
|
||||
public partial class HomePage : ContentPage
|
||||
{
|
||||
|
||||
private List<Term> _terms = [];
|
||||
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_ = RefreshTermList();
|
||||
}
|
||||
|
||||
private async Task RefreshTermList()
|
||||
{
|
||||
_terms.Clear();
|
||||
_terms = await DatabaseService.GetAllTerms();
|
||||
|
||||
TermButtonStack.Children.Clear();
|
||||
|
||||
|
||||
|
||||
foreach (var term in _terms)
|
||||
{
|
||||
var btn = new CustomButton()
|
||||
{
|
||||
Text = term.Name,
|
||||
DateText = $"{DateOnly.FromDateTime(term.StartDate).ToString()} - {DateOnly.FromDateTime(term.EndDate).ToString()}"
|
||||
};
|
||||
|
||||
TermButtonStack.Add(btn);
|
||||
|
||||
btn.Clicked += (sender, e) =>
|
||||
{
|
||||
HandleTermButtonClick(term);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void AddTermButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var newTerm = new Term()
|
||||
{
|
||||
Name = "New Term",
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30)
|
||||
};
|
||||
|
||||
await DatabaseService.AddTerm(newTerm);
|
||||
|
||||
await RefreshTermList();
|
||||
}
|
||||
|
||||
protected override async void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
await RefreshTermList();
|
||||
}
|
||||
|
||||
private void HandleTermButtonClick(Term term)
|
||||
{
|
||||
Navigation.PushAsync(new TermPage(term));
|
||||
}
|
||||
|
||||
private void TestButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Navigation.PushAsync(new TestPage());
|
||||
}
|
||||
}
|
||||
134
WguApp/Views/TermPage.xaml
Normal file
134
WguApp/Views/TermPage.xaml
Normal file
@@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Views.TermPage"
|
||||
Title="Term">
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Save"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=AliceBlue}"
|
||||
Clicked="SaveButton_OnClicked"/>
|
||||
<ToolbarItem Text="Delete"
|
||||
Order="Primary"
|
||||
Priority="0"
|
||||
IconImageSource="{FontImageSource Glyph='', FontFamily='Phosphor', Size=20, Color=Red}"
|
||||
Clicked="DeleteButton_OnClicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<Grid RowDefinitions="*">
|
||||
<ScrollView HorizontalOptions="Fill"
|
||||
HorizontalScrollBarVisibility="Never">
|
||||
<VerticalStackLayout HorizontalOptions="Fill">
|
||||
<Label Text="Term Info"
|
||||
FontAttributes="Bold"
|
||||
FontSize="20"
|
||||
Margin="20, 10, 20, 5"/>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Title:"
|
||||
VerticalOptions="Center"
|
||||
FontAttributes="Bold" />
|
||||
|
||||
<Entry x:Name="TitleEntry"
|
||||
Grid.Column="1"
|
||||
Placeholder="Enter value here..."
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Start date:"
|
||||
VerticalOptions="Center"
|
||||
FontAttributes="Bold" />
|
||||
|
||||
<DatePicker x:Name="StartDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *"
|
||||
ColumnSpacing="10"
|
||||
Padding="5"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="20, 10">
|
||||
|
||||
<Label Grid.Column="0"
|
||||
Text="Expected end date:"
|
||||
VerticalOptions="Center"
|
||||
FontAttributes="Bold" />
|
||||
|
||||
<DatePicker x:Name="EndDatePicker"
|
||||
Grid.Column="1"
|
||||
VerticalOptions="Center"
|
||||
WidthRequest="200"
|
||||
HorizontalOptions="End" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid RowDefinitions="*, Auto"
|
||||
ColumnDefinitions="*, Auto"
|
||||
HorizontalOptions="Fill"
|
||||
HeightRequest="40"
|
||||
Margin="30, 20, 30, 0">
|
||||
|
||||
<Label Text="Courses"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontSize="15"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Fill"
|
||||
HorizontalTextAlignment="Start"
|
||||
HeightRequest="20" />
|
||||
|
||||
<Button Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Text=""
|
||||
FontFamily="Phosphor"
|
||||
FontSize="15"
|
||||
WidthRequest="20"
|
||||
HeightRequest="20"
|
||||
TextColor="AliceBlue"
|
||||
BackgroundColor="Transparent"
|
||||
HorizontalOptions="End"
|
||||
VerticalOptions="Center"
|
||||
Clicked="AddCourseButton_OnClicked"/>
|
||||
</Grid>
|
||||
|
||||
<BoxView
|
||||
Color="AliceBlue"
|
||||
HeightRequest="2"
|
||||
HorizontalOptions="Fill"
|
||||
Margin="30, 0, 30, 20" />
|
||||
|
||||
|
||||
|
||||
<VerticalStackLayout x:Name="CourseButtonStack"
|
||||
Margin="30,10"
|
||||
HorizontalOptions="Fill"
|
||||
Spacing="5"/>
|
||||
</VerticalStackLayout>
|
||||
|
||||
</ScrollView>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
147
WguApp/Views/TermPage.xaml.cs
Normal file
147
WguApp/Views/TermPage.xaml.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using WguApp.Controls;
|
||||
using WguApp.Models;
|
||||
using WguApp.Services;
|
||||
|
||||
namespace WguApp.Views;
|
||||
|
||||
public partial class TermPage : ContentPage
|
||||
{
|
||||
|
||||
private Term _term;
|
||||
|
||||
private List<Course> _courses = [];
|
||||
|
||||
public TermPage(Term term)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_term = term;
|
||||
|
||||
Title = string.IsNullOrWhiteSpace(_term.Name) ? "Term" : _term.Name;
|
||||
TitleEntry.Text = _term.Name;
|
||||
|
||||
StartDatePicker.Date = _term.StartDate;
|
||||
EndDatePicker.Date = _term.EndDate;
|
||||
}
|
||||
|
||||
private async Task RefreshCourseList()
|
||||
{
|
||||
_courses.Clear();
|
||||
_courses = await DatabaseService.GetCoursesByTermId(_term.Id);
|
||||
|
||||
CourseButtonStack.Children.Clear();
|
||||
|
||||
foreach (var course in _courses)
|
||||
{
|
||||
var btn = new CustomButton()
|
||||
{
|
||||
Text = course.Name,
|
||||
DateText = $"{DateOnly.FromDateTime(course.StartDate).ToString()} - {DateOnly.FromDateTime(course.EndDate).ToString()}"
|
||||
};
|
||||
|
||||
CourseButtonStack.Add(btn);
|
||||
|
||||
btn.Clicked += (sender, e) =>
|
||||
{
|
||||
HandleCourseButtonClick(course);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override async void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RefreshCourseList();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await DisplayAlert("Error", e.Message, "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
private async void HandleCourseButtonClick(Course course)
|
||||
{
|
||||
await Navigation.PushAsync(new CoursePage(course));
|
||||
}
|
||||
|
||||
private async void SaveButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var validationResult = ValidateFields();
|
||||
|
||||
if (!validationResult.result)
|
||||
{
|
||||
await DisplayAlert("Validation Error", validationResult.msg, "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
_term.Name = TitleEntry.Text;
|
||||
_term.StartDate = StartDatePicker.Date;
|
||||
_term.EndDate = EndDatePicker.Date;
|
||||
|
||||
var updateResult = await DatabaseService.UpdateTerm(_term);
|
||||
|
||||
if (updateResult)
|
||||
{
|
||||
await DisplayAlert("Info", $"{_term.Name} Saved!", "Ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
await DisplayAlert("Error", "Could not save term", "Ok");
|
||||
}
|
||||
|
||||
Title = _term.Name;
|
||||
}
|
||||
|
||||
private (string msg, bool result) ValidateFields()
|
||||
{
|
||||
var message = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(TitleEntry.Text)) message += "Title cannot be blank\n";
|
||||
if (StartDatePicker.Date > EndDatePicker.Date) message += "Start Date cannot be after the End Date\n";
|
||||
|
||||
return string.IsNullOrWhiteSpace(message) ? (message, true) : (message, false);
|
||||
}
|
||||
|
||||
private async void DeleteButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var result = await DisplayAlert("Delete Term", $"Do you really want to delete '{_term.Name}'? This action cannot be undone.", "Delete", "Cancel");
|
||||
if (!result) return;
|
||||
|
||||
await DatabaseService.DeleteTerm(_term);
|
||||
await Navigation.PopAsync();
|
||||
}
|
||||
|
||||
private async void AddCourseButton_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (_courses.Count >= 6)
|
||||
{
|
||||
await DisplayAlert("Info", $"Cannot add more than 6 courses per term", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
var course = new Course()
|
||||
{
|
||||
TermId = _term.Id,
|
||||
Name = "New Course",
|
||||
StartDate = DateTime.Today,
|
||||
EndDate = DateTime.Today.AddDays(30),
|
||||
InstructorName = "",
|
||||
InstructorEmail = "",
|
||||
InstructorPhone = "",
|
||||
StartNotifCheck = false,
|
||||
EndNotifCheck = false,
|
||||
Status = CourseStatus.Planned,
|
||||
Notes = ""
|
||||
};
|
||||
|
||||
await DatabaseService.AddCourse(course);
|
||||
|
||||
await RefreshCourseList();
|
||||
}
|
||||
}
|
||||
39
WguApp/Views/TestPage.xaml
Normal file
39
WguApp/Views/TestPage.xaml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WguApp.Views.TestPage"
|
||||
Title="Test">
|
||||
<ContentPage.Content>
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Button
|
||||
Text="Test notification"
|
||||
Clicked="TestBtn_OnClicked"/>
|
||||
|
||||
<Button Text="List scheduled notifications"
|
||||
Clicked="ListNotifs_Clicked"/>
|
||||
|
||||
<Button Text="Clear all notifications"
|
||||
Clicked="ClearAllNotifs_Clicked"/>
|
||||
|
||||
<Button Text="Test Share"
|
||||
Clicked="ShareButton_OnClick"/>
|
||||
|
||||
<Button
|
||||
Text="Add sample data"
|
||||
Clicked="AddData_OnCLicked"></Button>
|
||||
|
||||
<Button Text="Delete data"
|
||||
Clicked="Delete_OnClicked"/>
|
||||
|
||||
<Button Text="Test logger"
|
||||
Clicked="TestLogger_Clicked"/>
|
||||
|
||||
<Button Text="Show log file"
|
||||
Clicked="ShowLog_Clicked"/>
|
||||
|
||||
<Button Text="Clear Log"
|
||||
Clicked="ClearLog_Clicked"/>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
120
WguApp/Views/TestPage.xaml.cs
Normal file
120
WguApp/Views/TestPage.xaml.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Plugin.LocalNotification;
|
||||
using WguApp.Services;
|
||||
|
||||
namespace WguApp.Views;
|
||||
|
||||
public partial class TestPage : ContentPage
|
||||
{
|
||||
public TestPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void TestBtn_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (await LocalNotificationCenter.Current.AreNotificationsEnabled() == false)
|
||||
{
|
||||
await LocalNotificationCenter.Current.RequestNotificationPermission();
|
||||
}
|
||||
|
||||
var notification = new NotificationRequest
|
||||
{
|
||||
NotificationId = 1,
|
||||
Title = "Notification Test",
|
||||
Description = "Success!",
|
||||
Schedule =
|
||||
{
|
||||
NotifyTime = DateTime.Now.AddSeconds(30),
|
||||
RepeatType = NotificationRepeat.No
|
||||
}
|
||||
};
|
||||
await LocalNotificationCenter.Current.Show(notification);
|
||||
|
||||
await DisplayAlert("Info", "A test notification should appear in 30 seconds", "ok");
|
||||
}
|
||||
|
||||
private async void AddData_OnCLicked(object? sender, EventArgs e)
|
||||
{
|
||||
var result = await DisplayAlert("Load Sample Data", "Do you really want to load DB sample data? This will delete ALL data from the database. This action cannot be undone.", "Yes", "No");
|
||||
if (!result) return;
|
||||
|
||||
await DatabaseService.LoadSampleData();
|
||||
|
||||
var terms = await DatabaseService.GetAllTerms();
|
||||
var courses = await DatabaseService.GetAllCourses();
|
||||
var assessments = await DatabaseService.GetAllAssessments();
|
||||
|
||||
await DisplayAlert("Info", $"Tried to load sample db data, there are now {terms.Count} Terms, {courses.Count} Courses, and {assessments.Count} Assessments", "Ok");
|
||||
}
|
||||
|
||||
private async void Delete_OnClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var terms = await DatabaseService.GetAllTerms();
|
||||
var courses = await DatabaseService.GetAllCourses();
|
||||
var assessments = await DatabaseService.GetAllAssessments();
|
||||
|
||||
var result = await DisplayAlert("Delete DB Data", $"Do you really want to delete the DB data? This will delete ALL data from the database. This action cannot be undone.\nThere are currently {terms.Count} Terms, {courses.Count} Courses, and {assessments.Count} Assessments", "Yes", "No");
|
||||
if (!result) return;
|
||||
|
||||
await DatabaseService.ClearDbData();
|
||||
|
||||
terms = await DatabaseService.GetAllTerms();
|
||||
courses = await DatabaseService.GetAllCourses();
|
||||
assessments = await DatabaseService.GetAllAssessments();
|
||||
|
||||
await DisplayAlert("Info", $"Tried to delete db data, there are now {terms.Count} Terms, {courses.Count} Courses, and {assessments.Count} Assessments", "Ok");
|
||||
}
|
||||
|
||||
private async void ShareButton_OnClick(object? sender, EventArgs e)
|
||||
{
|
||||
await Share.Default.RequestAsync(new ShareTextRequest
|
||||
{
|
||||
Text = "Test Share Text",
|
||||
Title = "Share Text"
|
||||
});
|
||||
}
|
||||
|
||||
private async void ListNotifs_Clicked(object? sender, EventArgs e)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
|
||||
var message = pendingNotifs.Aggregate($"-- Scheduled notifications ({pendingNotifs.Count}) --\n",
|
||||
(current, notif) => current + $"{notif.Title} : {notif.Schedule.NotifyTime}\n");
|
||||
|
||||
await DisplayAlert("Info", message, "Ok");
|
||||
}
|
||||
|
||||
private void TestLogger_Clicked(object? sender, EventArgs e)
|
||||
{
|
||||
LoggerService.LogToFile("Test");
|
||||
}
|
||||
|
||||
private async void ClearAllNotifs_Clicked(object? sender, EventArgs e)
|
||||
{
|
||||
var pendingNotifs = await LocalNotificationCenter.Current.GetPendingNotificationList();
|
||||
|
||||
foreach (var notificationRequest in pendingNotifs)
|
||||
{
|
||||
await LocalNotificationService.CancelNotification(notificationRequest.NotificationId);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ShowLog_Clicked(object? sender, EventArgs e)
|
||||
{
|
||||
var logFilePath = Path.Combine(FileSystem.AppDataDirectory, "log.txt");
|
||||
|
||||
await DisplayAlert("Log", await File.ReadAllTextAsync(logFilePath), "Ok");
|
||||
}
|
||||
|
||||
private void ClearLog_Clicked(object? sender, EventArgs e)
|
||||
{
|
||||
var logFilePath = Path.Combine(FileSystem.AppDataDirectory, "log.txt");
|
||||
|
||||
File.WriteAllText(logFilePath, "");
|
||||
}
|
||||
}
|
||||
70
WguApp/WguApp.csproj
Normal file
70
WguApp/WguApp.csproj
Normal file
@@ -0,0 +1,70 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
|
||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
|
||||
|
||||
<!-- Note for MacCatalyst:
|
||||
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
|
||||
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
|
||||
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
|
||||
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
|
||||
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>WguApp</RootNamespace>
|
||||
<UseMaui>true</UseMaui>
|
||||
<SingleProject>true</SingleProject>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<!-- Display name -->
|
||||
<ApplicationTitle>WguApp</ApplicationTitle>
|
||||
|
||||
<!-- App Identifier -->
|
||||
<ApplicationId>com.chrisbell.wguapp</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4"/>
|
||||
|
||||
<!-- Splash Screen -->
|
||||
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128"/>
|
||||
|
||||
<!-- Images -->
|
||||
<MauiImage Include="Resources\Images\*"/>
|
||||
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185"/>
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<MauiFont Include="Resources\Fonts\*"/>
|
||||
|
||||
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.8"/>
|
||||
<PackageReference Include="Plugin.LocalNotification" Version="12.0.2" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.10.196-beta" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.11" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
16
WguApp/WguApp.sln
Normal file
16
WguApp/WguApp.sln
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WguApp", "WguApp.csproj", "{BB2F04F1-B5E0-4852-8AAA-AD1AB18D7011}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BB2F04F1-B5E0-4852-8AAA-AD1AB18D7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BB2F04F1-B5E0-4852-8AAA-AD1AB18D7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BB2F04F1-B5E0-4852-8AAA-AD1AB18D7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BB2F04F1-B5E0-4852-8AAA-AD1AB18D7011}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
2
WguApp/WguApp.sln.DotSettings.user
Normal file
2
WguApp/WguApp.sln.DotSettings.user
Normal file
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADateOnly_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FUsers_003Fchris_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fb7bf1a4162ee5b47e01ff05d38423e295c7bbb45f3c7b3b77ab51d949e7e741b_003FDateOnly_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||
Reference in New Issue
Block a user