diff --git a/Sources/ConsoleApplication/Utils.cs b/Sources/ConsoleApplication/Utils.cs index fb70443..fec49ea 100644 --- a/Sources/ConsoleApplication/Utils.cs +++ b/Sources/ConsoleApplication/Utils.cs @@ -36,7 +36,7 @@ namespace ConsoleApplication switch (choix) { case "1": - //Console.WriteLine("# result : "+ await championsManager.GetNbItems()); + Console.WriteLine("# result : "+ await championsManager.GetNbItems()); break; case "2": var list = await championsManager.GetItems(0, 10); diff --git a/Sources/HttpClient/HttpClientManager.Champion.cs b/Sources/HttpClient/HttpClientManager.Champion.cs index fa2eed6..5eed5c0 100644 --- a/Sources/HttpClient/HttpClientManager.Champion.cs +++ b/Sources/HttpClient/HttpClientManager.Champion.cs @@ -44,6 +44,7 @@ namespace HttpClient public async Task DeleteItem(Champion? item) { HttpResponseMessage response = await httpc.DeleteAsync("v1/Champions?Name=" + item.Name); + _ = response.StatusCode; return response.IsSuccessStatusCode; } @@ -70,28 +71,30 @@ namespace HttpClient public Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false) { - return httpc.GetFromJsonAsync>("/Champion?name="+substring+"&index=" + index + "&size=" + count); + return httpc.GetFromJsonAsync>("v1/Champions?name=" + substring+"&index=" + index + "&size=" + count); } - public Task> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null, bool descending = false) + public Task GetNbItems() { - throw new NotImplementedException(); + return httpc.GetFromJsonAsync("v1/Champions/count"); } - public Task> GetItemsBySkill(Skill? skill, int index, int count, string? orderingPropertyName = null, bool descending = false) + + public Task> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null, bool descending = false) { throw new NotImplementedException(); } - public Task> GetItemsBySkill(string skill, int index, int count, string? orderingPropertyName = null, bool descending = false) + public Task> GetItemsBySkill(Skill? skill, int index, int count, string? orderingPropertyName = null, bool descending = false) { throw new NotImplementedException(); } - public Task GetNbItems() + public Task> GetItemsBySkill(string skill, int index, int count, string? orderingPropertyName = null, bool descending = false) { throw new NotImplementedException(); } + public Task GetNbItemsByCharacteristic(string charName) { @@ -123,9 +126,13 @@ namespace HttpClient throw new NotImplementedException(); } - public Task UpdateItem(Champion? oldItem, Champion? newItem) + public async Task UpdateItem(Champion? oldItem, Champion? newItem) { - throw new NotImplementedException(); + HttpResponseMessage rep = await httpc.PutAsJsonAsync("v1/Champions?name=" + oldItem.Name, newItem.ToDTO()); + + if (rep.IsSuccessStatusCode) return newItem; + //else + return null; } } } diff --git a/Sources/LeagueOfLegends.sln b/Sources/LeagueOfLegends.sln index 4ce78a2..dbf8519 100644 --- a/Sources/LeagueOfLegends.sln +++ b/Sources/LeagueOfLegends.sln @@ -30,7 +30,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpClient", "HttpClient\Ht EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{6570AF99-3E74-4CAA-AEB0-EEFE4F79780F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication", "ConsoleApplication\ConsoleApplication.csproj", "{53A195F7-FB7C-44E8-AB82-4D775C7D9477}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApplication", "ConsoleApplication\ConsoleApplication.csproj", "{53A195F7-FB7C-44E8-AB82-4D775C7D9477}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LolApp", "LolApp\LolApp.csproj", "{0C898A04-092A-49AA-BE65-8AE818A2AF50}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModels", "ViewModels\ViewModels.csproj", "{D398A62C-1E70-4B45-8717-440681EEBBFE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -78,6 +82,14 @@ Global {53A195F7-FB7C-44E8-AB82-4D775C7D9477}.Debug|Any CPU.Build.0 = Debug|Any CPU {53A195F7-FB7C-44E8-AB82-4D775C7D9477}.Release|Any CPU.ActiveCfg = Release|Any CPU {53A195F7-FB7C-44E8-AB82-4D775C7D9477}.Release|Any CPU.Build.0 = Release|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.Build.0 = Release|Any CPU + {D398A62C-1E70-4B45-8717-440681EEBBFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D398A62C-1E70-4B45-8717-440681EEBBFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D398A62C-1E70-4B45-8717-440681EEBBFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D398A62C-1E70-4B45-8717-440681EEBBFE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sources/LolApp/AddChampionPage.xaml b/Sources/LolApp/AddChampionPage.xaml new file mode 100644 index 0000000..7f38acb --- /dev/null +++ b/Sources/LolApp/AddChampionPage.xaml @@ -0,0 +1,142 @@ + + + + + + + + + diff --git a/Sources/LolApp/ChampionsPage.xaml.cs b/Sources/LolApp/ChampionsPage.xaml.cs new file mode 100644 index 0000000..4493526 --- /dev/null +++ b/Sources/LolApp/ChampionsPage.xaml.cs @@ -0,0 +1,17 @@ +using LolApp.ViewModels; +using ViewModels; + +namespace LolApp; + +public partial class ChampionsPage : ContentPage +{ + public ApplicationVM AppVM { get; } + public ChampionsPageVM VM { get; } + public ChampionsPage(ApplicationVM appVM) + { + InitializeComponent(); + AppVM = appVM; + VM = new ChampionsPageVM(AppVM.ChampionsMgrVM); + BindingContext = this; + } +} diff --git a/Sources/LolApp/ContentViews/ChampionClassSelector.xaml b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml new file mode 100644 index 0000000..6dc66e4 --- /dev/null +++ b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml @@ -0,0 +1,131 @@ + + + + + Assassin + Fighter + Mage + Marksman + Support + Tank + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs new file mode 100644 index 0000000..74fb508 --- /dev/null +++ b/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs @@ -0,0 +1,34 @@ +using Model; + +namespace LolApp.ContentViews; + +public partial class ChampionClassSelector : ContentView +{ + public ChampionClassSelector() + { + InitializeComponent(); + } + + public static readonly BindableProperty SelectedValueProperty = BindableProperty.Create(nameof(SelectedValue), typeof(ChampionClass), typeof(ChampionClassSelector), ChampionClass.Unknown, BindingMode.TwoWay); + public ChampionClass SelectedValue + { + get => (ChampionClass)GetValue(SelectedValueProperty); + set => SetValue(SelectedValueProperty, value); + } + + public static readonly BindableProperty CheckedColorProperty = BindableProperty.Create(nameof(CheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon); + + public Color CheckedColor + { + get => (Color)GetValue(CheckedColorProperty); + set => SetValue(CheckedColorProperty, value); + } + + public static readonly BindableProperty UncheckedColorProperty = BindableProperty.Create(nameof(UncheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon); + + public Color UncheckedColor + { + get => (Color)GetValue(UncheckedColorProperty); + set => SetValue(UncheckedColorProperty, value); + } +} diff --git a/Sources/LolApp/ContentViews/SearchByStringView.cs b/Sources/LolApp/ContentViews/SearchByStringView.cs new file mode 100644 index 0000000..308ce0d --- /dev/null +++ b/Sources/LolApp/ContentViews/SearchByStringView.cs @@ -0,0 +1,38 @@ +using System.Windows.Input; + +namespace LolApp.ContentViews; + +public class SearchByStringView : ContentView +{ + public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(nameof(PlaceHolder), typeof(string), typeof(SearchByStringView), string.Empty); + + public string PlaceHolder + { + get => (string)GetValue(PlaceHolderProperty); + set => SetValue(PlaceHolderProperty, value); + } + + public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(SearchByStringView), string.Empty); + + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(SearchByStringView), null); + + public ICommand Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + + public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(SearchByStringView), null); + + public object CommandParameter + { + get => GetValue(CommandParameterProperty); + set => SetValue(CommandParameterProperty, value); + } +} diff --git a/Sources/LolApp/LolApp.csproj b/Sources/LolApp/LolApp.csproj new file mode 100644 index 0000000..e1a06ae --- /dev/null +++ b/Sources/LolApp/LolApp.csproj @@ -0,0 +1,99 @@ + + + + net7.0-android;net7.0-ios;net7.0-maccatalyst + Exe + LolApp + true + true + enable + + + LolApp + + + fr.uca.iut.lolapp + d3cd18a9-c614-4933-bd36-3008e72004d5 + + + 1.0 + 1 + + 14.2 + 14.0 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + {0C898A04-092A-49AA-BE65-8AE818A2AF50} + + + + false + appleIUT_TP2022 + iPhone Developer: Cedric BOUHOURS (M2E3ZQNZ3K) + + + false + Developer ID Application + 3rd Party Mac Developer Installer + + + false + + + $(TargetFrameworks);net7.0-windows10.0.22621.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/MainPage.xaml b/Sources/LolApp/MainPage.xaml new file mode 100644 index 0000000..9db8163 --- /dev/null +++ b/Sources/LolApp/MainPage.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/Sources/LolApp/MainPage.xaml.cs b/Sources/LolApp/MainPage.xaml.cs new file mode 100644 index 0000000..0750b67 --- /dev/null +++ b/Sources/LolApp/MainPage.xaml.cs @@ -0,0 +1,11 @@ +namespace LolApp; + +public partial class MainPage : ContentPage +{ + public MainPage() + { + InitializeComponent(); + } +} + + diff --git a/Sources/LolApp/MauiProgram.cs b/Sources/LolApp/MauiProgram.cs new file mode 100644 index 0000000..dfe7d83 --- /dev/null +++ b/Sources/LolApp/MauiProgram.cs @@ -0,0 +1,39 @@ +using CommunityToolkit.Maui; +using LolApp.ViewModels; +using Microsoft.Extensions.Logging; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; +using Model; +using StubLib; +using ViewModels; + +namespace LolApp; + +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .UseMauiCommunityToolkit() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + fonts.AddFont("Font Awesome 6 Free-Solid-900.otf", "FASolid"); + }); + builder.Services.AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } +} + diff --git a/Sources/LolApp/Platforms/Android/AndroidManifest.xml b/Sources/LolApp/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..e6c8a36 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Sources/LolApp/Platforms/Android/MainActivity.cs b/Sources/LolApp/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..016887c --- /dev/null +++ b/Sources/LolApp/Platforms/Android/MainActivity.cs @@ -0,0 +1,11 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace LolApp; + +[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] +public class MainActivity : MauiAppCompatActivity +{ +} + diff --git a/Sources/LolApp/Platforms/Android/MainApplication.cs b/Sources/LolApp/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..95e1d92 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/MainApplication.cs @@ -0,0 +1,16 @@ +using Android.App; +using Android.Runtime; + +namespace LolApp; + +[Application] +public class MainApplication : MauiApplication +{ + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/Android/Resources/values/colors.xml b/Sources/LolApp/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c2794f7 --- /dev/null +++ b/Sources/LolApp/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,7 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + + diff --git a/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs b/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..d5d15a5 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace LolApp; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/MacCatalyst/Info.plist b/Sources/LolApp/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..ec44095 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,36 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSCameraUsageDescription + New Entry + NSPhotoLibraryUsageDescription + New Entry + NSPhotoLibraryAddUsageDescription + New Entry + + diff --git a/Sources/LolApp/Platforms/MacCatalyst/Program.cs b/Sources/LolApp/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..f1b8f29 --- /dev/null +++ b/Sources/LolApp/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace LolApp; + +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)); + } +} + diff --git a/Sources/LolApp/Platforms/Tizen/Main.cs b/Sources/LolApp/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..d58b3d9 --- /dev/null +++ b/Sources/LolApp/Platforms/Tizen/Main.cs @@ -0,0 +1,17 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Hosting; + +namespace LolApp; + +class Program : MauiApplication +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } +} + diff --git a/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml b/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..109d29f --- /dev/null +++ b/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + diff --git a/Sources/LolApp/Platforms/Windows/App.xaml b/Sources/LolApp/Platforms/Windows/App.xaml new file mode 100644 index 0000000..23c64b9 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/App.xaml @@ -0,0 +1,9 @@ + + + + diff --git a/Sources/LolApp/Platforms/Windows/App.xaml.cs b/Sources/LolApp/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..c3b0669 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/App.xaml.cs @@ -0,0 +1,25 @@ +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 LolApp.WinUI; + +/// +/// Provides application-specific behavior to supplement the default Application class. +/// +public partial class App : MauiWinUIApplication +{ + /// + /// 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(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + + diff --git a/Sources/LolApp/Platforms/Windows/Package.appxmanifest b/Sources/LolApp/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..52b7801 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,47 @@ + + + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/Platforms/Windows/app.manifest b/Sources/LolApp/Platforms/Windows/app.manifest new file mode 100644 index 0000000..91a1b32 --- /dev/null +++ b/Sources/LolApp/Platforms/Windows/app.manifest @@ -0,0 +1,16 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + + diff --git a/Sources/LolApp/Platforms/iOS/AppDelegate.cs b/Sources/LolApp/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..d5d15a5 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace LolApp; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/Sources/LolApp/Platforms/iOS/Info.plist b/Sources/LolApp/Platforms/iOS/Info.plist new file mode 100644 index 0000000..352a326 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/Info.plist @@ -0,0 +1,38 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSCameraUsageDescription + New Entry + NSPhotoLibraryUsageDescription + Pour accéder aux images... + NSPhotoLibraryAddUsageDescription + Pour accéder aux images... + + diff --git a/Sources/LolApp/Platforms/iOS/Program.cs b/Sources/LolApp/Platforms/iOS/Program.cs new file mode 100644 index 0000000..f1b8f29 --- /dev/null +++ b/Sources/LolApp/Platforms/iOS/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace LolApp; + +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)); + } +} + diff --git a/Sources/LolApp/Properties/launchSettings.json b/Sources/LolApp/Properties/launchSettings.json new file mode 100644 index 0000000..90f92d9 --- /dev/null +++ b/Sources/LolApp/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} diff --git a/Sources/LolApp/Resources/AppIcon/appicon.png b/Sources/LolApp/Resources/AppIcon/appicon.png new file mode 100644 index 0000000..8263b46 Binary files /dev/null and b/Sources/LolApp/Resources/AppIcon/appicon.png differ diff --git a/Sources/LolApp/Resources/AppIcon/appiconfg.svg b/Sources/LolApp/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..e9b7139 --- /dev/null +++ b/Sources/LolApp/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs b/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs new file mode 100644 index 0000000..e258576 --- /dev/null +++ b/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using CommunityToolkit.Maui.Converters; + +namespace LolApp.Resources.Converters +{ + public class Base64ToImageSourceConverter : ByteArrayToImageSourceConverter, IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + string base64 = value as string; + if (string.IsNullOrWhiteSpace(base64)) return null; + try + { + byte[] bytes = System.Convert.FromBase64String(base64); + return base.ConvertFrom(bytes, culture); + } + catch + { + return null; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + ImageSource source = value as ImageSource; + if (source == null) return null; + byte[] bytes = base.ConvertBackTo(source, culture) as byte[]; + return System.Convert.ToBase64String(bytes); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs b/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs new file mode 100644 index 0000000..946b9a6 --- /dev/null +++ b/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Globalization; +using Model; + +namespace LolApp.Resources.Converters +{ + public class ChampionClassToIconConverter : IValueConverter + { + private static Dictionary icons = new() + { + [ChampionClass.Assassin] = "assassin.png", + [ChampionClass.Fighter] = "fighter.png", + [ChampionClass.Mage] = "mage.png", + [ChampionClass.Marksman] = "marksman.png", + [ChampionClass.Support] = "support.png", + [ChampionClass.Tank] = "tank.png" + }; + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + ChampionClass champClass = (ChampionClass)value; + if(!icons.TryGetValue(champClass, out string icon)) + { + return ""; + } + return ImageSource.FromFile($"{icon}"); + } + catch + { + return ""; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs b/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs new file mode 100644 index 0000000..a3e0b7e --- /dev/null +++ b/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; + +namespace LolApp.Resources.Converters +{ + public class ImageRatioConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + double parentWidth = (double)value; + double ratio = (double)parameter; + return parentWidth*ratio; + } + catch + { + return 0.0; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Converters/PlusOneConverter.cs b/Sources/LolApp/Resources/Converters/PlusOneConverter.cs new file mode 100644 index 0000000..2d9eaec --- /dev/null +++ b/Sources/LolApp/Resources/Converters/PlusOneConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; + +namespace LolApp.Resources.Converters +{ + public class PlusOneConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + int i = -1; + try + { + i = (int)value; + } + catch (InvalidCastException e) + { + throw new InvalidCastException("PlusOneConverter : the value must be an int"); + } + return i + 1; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} + diff --git a/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf b/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf new file mode 100644 index 0000000..f1d88fc Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf differ diff --git a/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf b/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..a49f11d Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf b/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..23911e4 Binary files /dev/null and b/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/Sources/LolApp/Resources/Images/assassin.svg b/Sources/LolApp/Resources/Images/assassin.svg new file mode 100644 index 0000000..fb86680 --- /dev/null +++ b/Sources/LolApp/Resources/Images/assassin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/fighter.svg b/Sources/LolApp/Resources/Images/fighter.svg new file mode 100644 index 0000000..42cb7df --- /dev/null +++ b/Sources/LolApp/Resources/Images/fighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/lol.png b/Sources/LolApp/Resources/Images/lol.png new file mode 100644 index 0000000..10a552c Binary files /dev/null and b/Sources/LolApp/Resources/Images/lol.png differ diff --git a/Sources/LolApp/Resources/Images/lollogo.jpg b/Sources/LolApp/Resources/Images/lollogo.jpg new file mode 100644 index 0000000..a1b82b5 Binary files /dev/null and b/Sources/LolApp/Resources/Images/lollogo.jpg differ diff --git a/Sources/LolApp/Resources/Images/mage.svg b/Sources/LolApp/Resources/Images/mage.svg new file mode 100644 index 0000000..45d627b --- /dev/null +++ b/Sources/LolApp/Resources/Images/mage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/marksman.svg b/Sources/LolApp/Resources/Images/marksman.svg new file mode 100644 index 0000000..f91066f --- /dev/null +++ b/Sources/LolApp/Resources/Images/marksman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/rp.png b/Sources/LolApp/Resources/Images/rp.png new file mode 100644 index 0000000..e025310 Binary files /dev/null and b/Sources/LolApp/Resources/Images/rp.png differ diff --git a/Sources/LolApp/Resources/Images/support.svg b/Sources/LolApp/Resources/Images/support.svg new file mode 100644 index 0000000..2d1f053 --- /dev/null +++ b/Sources/LolApp/Resources/Images/support.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Images/sword.png b/Sources/LolApp/Resources/Images/sword.png new file mode 100644 index 0000000..fb87c07 Binary files /dev/null and b/Sources/LolApp/Resources/Images/sword.png differ diff --git a/Sources/LolApp/Resources/Images/tank.svg b/Sources/LolApp/Resources/Images/tank.svg new file mode 100644 index 0000000..2ec01a3 --- /dev/null +++ b/Sources/LolApp/Resources/Images/tank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Sources/LolApp/Resources/Raw/AboutAssets.txt b/Sources/LolApp/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..808d6d3 --- /dev/null +++ b/Sources/LolApp/Resources/Raw/AboutAssets.txt @@ -0,0 +1,17 @@ +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`. + + + +These files will be deployed with you 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(); + } + + diff --git a/Sources/LolApp/Resources/Splash/splash.png b/Sources/LolApp/Resources/Splash/splash.png new file mode 100644 index 0000000..e89e1c2 Binary files /dev/null and b/Sources/LolApp/Resources/Splash/splash.png differ diff --git a/Sources/LolApp/Resources/Styles/Colors.xaml b/Sources/LolApp/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..286775e --- /dev/null +++ b/Sources/LolApp/Resources/Styles/Colors.xaml @@ -0,0 +1,46 @@ + + + + + #D2B977 + #F0E7B7 + #2B0B98 + White + Black + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + #F7B548 + #FFD590 + #FFE5B9 + #28C2D1 + #7BDDEF + #C3F2F4 + #3E8EED + #72ACF1 + #A7CBF6 + + Transparent + + diff --git a/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml b/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml new file mode 100644 index 0000000..a53b993 --- /dev/null +++ b/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Sources/LolApp/Resources/Styles/MyStyles.xaml b/Sources/LolApp/Resources/Styles/MyStyles.xaml new file mode 100644 index 0000000..b988753 --- /dev/null +++ b/Sources/LolApp/Resources/Styles/MyStyles.xaml @@ -0,0 +1,102 @@ + + + + + 0.59 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/Resources/Styles/Styles.xaml b/Sources/LolApp/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..d23a11d --- /dev/null +++ b/Sources/LolApp/Resources/Styles/Styles.xaml @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/SkinPage.xaml b/Sources/LolApp/SkinPage.xaml new file mode 100644 index 0000000..0b082ab --- /dev/null +++ b/Sources/LolApp/SkinPage.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/LolApp/SkinPage.xaml.cs b/Sources/LolApp/SkinPage.xaml.cs new file mode 100644 index 0000000..901e3ec --- /dev/null +++ b/Sources/LolApp/SkinPage.xaml.cs @@ -0,0 +1,18 @@ +using LolApp.ViewModels; +using ViewModels; + +namespace LolApp; + +public partial class SkinPage : ContentPage +{ + public ApplicationVM AppVM { get; set; } + public SkinVM SkinVM { get; } + + public SkinPage(SkinVM svm, ApplicationVM appVM) + { + BindingContext = SkinVM = svm; + AppVM = appVM; + + InitializeComponent(); + } +} diff --git a/Sources/LolApp/ViewModels/AddChampionPageVM.cs b/Sources/LolApp/ViewModels/AddChampionPageVM.cs new file mode 100644 index 0000000..31fb1e3 --- /dev/null +++ b/Sources/LolApp/ViewModels/AddChampionPageVM.cs @@ -0,0 +1,80 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +//using Microsoft.Maui.Graphics.Platform; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class AddChampionPageVM + { + ChampionsMgrVM ChampionsMgrVM { get; } + + public AddChampionPageVM(ChampionsMgrVM championsMgrVM, ChampionVM champion = null) + { + ChampionsMgrVM = championsMgrVM; + if(champion == null) return; + + oldChampion = champion; + IsNew = false; + this.champion = new EditableChampionVM(oldChampion); + } + + private ChampionVM oldChampion; + + [ObservableProperty] + bool isNew = true; + + [ObservableProperty] + EditableChampionVM champion = new (); + + [RelayCommand] + public async void PickIcon() => Champion.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42); + + [RelayCommand] + public async void PickLargeImage() => Champion.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000); + + [RelayCommand] + async Task Cancel() + => await App.Current.MainPage.Navigation.PopAsync(); + + [RelayCommand] + async Task AddChampion() + { + ChampionVM champVM = Champion.ToChampionVM(); + await ChampionsMgrVM.AddChampion(champVM); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [RelayCommand] + async Task EditChampion() + { + ChampionVM newChampion = Champion.ToChampionVM(); + await ChampionsMgrVM.EditChampion(oldChampion, newChampion); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [ObservableProperty] + string newCharacteristicDescription; + + [ObservableProperty] + int newCharacteristicValue; + + [RelayCommand] + void AddCharacteristic() + { + Champion?.AddCharacteristic(newCharacteristicDescription, newCharacteristicValue); + } + + [RelayCommand] + void RemoveCharacteristic(KeyValuePair characteristic) + => Champion?.RemoveCharacteristic(characteristic); + + [RelayCommand] + async Task AddSkill() + => await App.Current.MainPage.Navigation.PushModalAsync(new AddSkill(Champion)); + + } +} + diff --git a/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs b/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs new file mode 100644 index 0000000..09a134c --- /dev/null +++ b/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs @@ -0,0 +1,64 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class AddOrEditSkinPageVM + { + SkinsMgrVM SkinsMgrVM { get; } + + private SkinVM oldSkin; + + [ObservableProperty] + bool isNew = true; + + [ObservableProperty] + EditableSkinVM skin; + + public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, SkinVM oldSkin) + { + SkinsMgrVM = skinsMgrVM; + + this.oldSkin = oldSkin; + IsNew = false; + this.skin = new EditableSkinVM(oldSkin); + } + + public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, ChampionVM champion) + { + SkinsMgrVM = skinsMgrVM; + skin = new EditableSkinVM(champion); + } + + [RelayCommand] + public async void PickIcon() => Skin.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42); + + [RelayCommand] + public async void PickLargeImage() => Skin.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000); + + [RelayCommand] + async Task Cancel() + => await App.Current.MainPage.Navigation.PopAsync(); + + [RelayCommand] + async Task AddSkin() + { + SkinVM skinVM = Skin.ToSkinVM(); + await SkinsMgrVM.AddSkin(skinVM); + await App.Current.MainPage.Navigation.PopAsync(); + } + + [RelayCommand] + async Task EditSkin() + { + SkinVM newSkin = Skin.ToSkinVM(); + await SkinsMgrVM.EditSkin(oldSkin, newSkin); + await App.Current.MainPage.Navigation.PopAsync(); + } + } +} + diff --git a/Sources/LolApp/ViewModels/AddSkillVM.cs b/Sources/LolApp/ViewModels/AddSkillVM.cs new file mode 100644 index 0000000..ef40e97 --- /dev/null +++ b/Sources/LolApp/ViewModels/AddSkillVM.cs @@ -0,0 +1,46 @@ +using System; +using System.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + public partial class AddSkillVM : ObservableObject + { + public AddSkillVM(EditableChampionVM champion) + { + Champion = champion; + } + + [ObservableProperty] + SkillType skillType; + + [ObservableProperty] + string name; + + [ObservableProperty] + string description; + + [ObservableProperty] + EditableChampionVM champion; + + [RelayCommand] + async void AddSkillToChampion() + { + champion.Skills.Add(new SkillVM(new Skill(name, skillType, description))); + await App.Current.MainPage.Navigation.PopModalAsync(); + } + + [RelayCommand] + async void Cancel() + { + await App.Current.MainPage.Navigation.PopModalAsync(); + } + + public IEnumerable AllSkills { get; } + = Enum.GetValues(typeof(SkillType)).Cast().Except(new SkillType[] {SkillType.Unknown}).ToList(); + } +} + diff --git a/Sources/LolApp/ViewModels/ApplicationVM.cs b/Sources/LolApp/ViewModels/ApplicationVM.cs new file mode 100644 index 0000000..9f029f0 --- /dev/null +++ b/Sources/LolApp/ViewModels/ApplicationVM.cs @@ -0,0 +1,58 @@ +using System; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + public partial class ApplicationVM + { + public ChampionsMgrVM ChampionsMgrVM { get; set; } + + public SkinsMgrVM SkinsMgrVM { get; set; } + + public ApplicationVM(ChampionsMgrVM championsMgrVM, SkinsMgrVM skinsMgrVM) + { + ChampionsMgrVM = championsMgrVM; + SkinsMgrVM = skinsMgrVM; + } + + [RelayCommand] + async Task NavigateToChampionDetailsPage(ChampionVM cvm) + { + SkinsMgrVM.Champion = cvm; + SkinsMgrVM.Index = 0; + SkinsMgrVM.Count = 5; + await SkinsMgrVM.LoadSkinsCommand.ExecuteAsync(cvm); + await App.Current.MainPage.Navigation.PushAsync(new ChampionPage(cvm, this)); + } + + [RelayCommand] + async Task NavigateToAddNewChampionPage() + => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM)); + + [RelayCommand(CanExecute = nameof(CanNavigateToEditChampionPage))] + async Task NavigateToEditChampionPage(object champ) + => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM, champ as ChampionVM)); + + bool CanNavigateToEditChampionPage(object champ) => champ != null && champ is ChampionVM; + + [RelayCommand] + async Task NavigateToSkinDetailsPage(object svm) + { + if (svm == null || svm is not SkinVM) return; + await App.Current.MainPage.Navigation.PushAsync(new SkinPage(svm as SkinVM, this)); + } + + [RelayCommand] + async Task NavigateToAddNewSkinPage(ChampionVM champion) + => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, champion)); + + [RelayCommand(CanExecute = nameof(CanNavigateToEditSkinPage))] + async Task NavigateToEditSkinPage(object skin) + => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, skin as SkinVM)); + + bool CanNavigateToEditSkinPage(object skin) => skin != null && skin is SkinVM; + } +} + diff --git a/Sources/LolApp/ViewModels/ChampionClassVM.cs b/Sources/LolApp/ViewModels/ChampionClassVM.cs new file mode 100644 index 0000000..992f45f --- /dev/null +++ b/Sources/LolApp/ViewModels/ChampionClassVM.cs @@ -0,0 +1,27 @@ +using System; +using System.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class ChampionClassVM + { + [ObservableProperty] + private ChampionClass model; + + [ObservableProperty] + private bool isSelected; + + public ChampionClassVM(ChampionClass model) + { + Model = model; + } + + public static IEnumerable Classes { get; } + = Enum.GetValues(typeof(ChampionClass)).Cast().Except(new ChampionClass[] {ChampionClass.Unknown}) + .Select(cc => new ChampionClassVM(cc)); + } +} + diff --git a/Sources/LolApp/ViewModels/ChampionsPageVM.cs b/Sources/LolApp/ViewModels/ChampionsPageVM.cs new file mode 100644 index 0000000..906875a --- /dev/null +++ b/Sources/LolApp/ViewModels/ChampionsPageVM.cs @@ -0,0 +1,111 @@ +using System; +using System.Reflection; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; +using ViewModels; + +namespace LolApp.ViewModels +{ + [ObservableObject] + public partial class ChampionsPageVM + { + public ChampionsMgrVM ChampionsMgrVM { get; set; } + + public ChampionsPageVM(ChampionsMgrVM championsMgrVM) + { + ChampionsMgrVM = championsMgrVM; + PropertyChanged += ChampionsMgrVM_PropertyChanged; + + } + + [ObservableProperty] + private ChampionClassVM selectedClass; + + + [RelayCommand] + public async Task SelectedChampionClassChanged(ChampionClassVM champClass) + { + if(SelectedClass != null) SelectedClass.IsSelected = false; + if(champClass.Model == ChampionClass.Unknown + || champClass.Model == SelectedClass?.Model) + { + SelectedClass = null; + return; + } + SelectedClass = champClass; + SelectedClass.IsSelected = true; + await ChampionsMgrVM.LoadChampionsByClass(SelectedClass.Model);//ChampionsMgrVM.SelectedClass); + + } + + + [ObservableProperty] + private ChampionVM selectedChampion; + + [ObservableProperty] + private string searchedName; + + + + [ObservableProperty] + private string searchedSkill; + + [ObservableProperty] + private string searchedCharacteristic; + + private static string[] searchedStrings = { nameof(SearchedName), nameof(SearchedSkill), nameof(SearchedCharacteristic), nameof(SelectedClass) }; + + private async void ChampionsMgrVM_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if(searchedStrings.Any(s => e.PropertyName == s)) + { + if(GetProperty(e.PropertyName).GetValue(this) != GetProperty(e.PropertyName).GetDefaultValue()) + { + foreach(string s in searchedStrings.Except(new string[]{e.PropertyName })) + { + var prop = GetProperty(s); + prop.ResetPropertyValue(this); + } + return; + } + ChampionsMgrVM.Index=0; + if(searchedStrings.All(s => GetProperty(s).GetValue(this) == GetProperty(s).GetDefaultValue())) + { + await ChampionsMgrVM.LoadChampions(); + } + } + } + + private PropertyInfo? GetProperty(string propName) + => typeof(ChampionsPageVM).GetProperty(propName); + + } + + public static class Extensions + { + public static void ResetPropertyValue(this PropertyInfo pi, ChampionsPageVM instance) + { + if(pi.PropertyType == typeof(ChampionClassVM)) + { + var temp = pi.GetValue(instance); + if(temp != null) + (temp as ChampionClassVM).IsSelected = false; + return; + } + pi.SetValue(instance, pi.GetDefaultValue()); + } + + public static object GetDefaultValue(this Type t) + { + if (t.IsValueType) + return Activator.CreateInstance(t); + + return null; + } + + public static object GetDefaultValue(this PropertyInfo pi) + => pi.PropertyType.GetDefaultValue(); + } +} + diff --git a/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs b/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs new file mode 100644 index 0000000..6cef1d1 --- /dev/null +++ b/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs @@ -0,0 +1,32 @@ +using System; +//using Microsoft.Maui.Graphics.Platform; +using Microsoft.Maui.Graphics.Skia; + +namespace LolApp.ViewModels +{ + public static class PickIconsAndImagesUtils + { + public async static Task PickPhoto(float maxWidthAndHeight) + { + FileResult photo = await MediaPicker.Default.PickPhotoAsync(); + return photo != null ? await ToBase64(photo, maxWidthAndHeight) : null; + } + + public async static Task ToBase64(FileResult photo, float maxWidthAndHeight) + { + using (var stream = await photo.OpenReadAsync()) + using (var memoryStream = new MemoryStream()) + { + var image = SkiaImage.FromStream(memoryStream); + //var image = PlatformImage.FromStream(stream); + if(image != null) + { + var newImage = image.Downsize(maxWidthAndHeight, true); + return newImage.AsBase64(); + } + } + return null; + } + } +} + diff --git a/Sources/ViewModels/ChampionVM.cs b/Sources/ViewModels/ChampionVM.cs new file mode 100644 index 0000000..bdd1e7f --- /dev/null +++ b/Sources/ViewModels/ChampionVM.cs @@ -0,0 +1,101 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; +using Microsoft.Maui.Controls; +using System.Collections.ObjectModel; + + +namespace ViewModels +{ + public partial class ChampionVM : ObservableObject + { + public Champion Model + { + get => model; + set + { + model = value; + OnPropertyChanged(nameof(Name)); + OnPropertyChanged(nameof(Bio)); + OnPropertyChanged(nameof(Class)); + OnPropertyChanged(nameof(Icon)); + OnPropertyChanged(nameof(Image)); + OnPropertyChanged(nameof(Skills)); + OnPropertyChanged(nameof(Characteristics)); + } + } + private Champion model; + + public ChampionVM(Champion model) + { + Model = model; + foreach(var skill in Model.Skills) + { + Skills.Add(new SkillVM(skill)); + } + Skills.CollectionChanged += Skills_CollectionChanged; + } + + private void Skills_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + SkillVM vm = e.NewItems?[0] as SkillVM; + switch(e.Action) + { + case System.Collections.Specialized.NotifyCollectionChangedAction.Add: + Model.Skills.Add(new Skill(vm.Name, vm.Type, vm.Description)); + break; + case System.Collections.Specialized.NotifyCollectionChangedAction.Remove: + Model.Skills.Remove(vm.Model); + break; + } + } + + public string Name => Model.Name; + + public ChampionClass Class + { + get => Model.Class; + set => SetProperty(Model.Class, value, newValue => Model.Class = newValue); + } + + public string Bio + { + get => Model.Bio; + set => SetProperty(Model.Bio, value, newBio => Model.Bio = newBio); + } + + public string Icon + { + get => Model.Icon; + set + { + SetProperty(Model.Icon, value, newIcon => + { + Model.Icon = newIcon; + }); + } + } + + public string Image + { + get => Model.Image.Base64; + set + { + SetProperty(Model.Image.Base64, value, newImage => + { + Model.Image.Base64 = newImage; + }); + } + } + + [ObservableProperty] + private ObservableCollection skills = new ObservableCollection(); + + public ReadOnlyDictionary Characteristics + => Model.Characteristics; + + [ObservableProperty] + private ObservableCollection skins = new ObservableCollection(); + } +} + diff --git a/Sources/ViewModels/ChampionsMgrVM.cs b/Sources/ViewModels/ChampionsMgrVM.cs new file mode 100644 index 0000000..06e5d67 --- /dev/null +++ b/Sources/ViewModels/ChampionsMgrVM.cs @@ -0,0 +1,227 @@ +using System.Threading.Tasks; +using Model; +using System.Windows.Input; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.Input; +using System.Data.SqlTypes; +using System.Reflection; + +namespace ViewModels; + +public partial class ChampionsMgrVM : ObservableObject +{ + internal IDataManager DataMgr { get; set; } + + public ChampionsMgrVM(IDataManager dataManager) + { + DataMgr = dataManager; + + loadingMethods = new Dictionary>() + { + [LoadingCriterium.None] = async (o) => await LoadChampions(), + [LoadingCriterium.ByName] = async (o) => + { + string substring = o as string; + if(substring == null) return; + await LoadChampionsByName(substring); + }, + [LoadingCriterium.BySkill] = async (o) => + { + string skillString = o as string; + if(skillString == null) return; + await LoadChampionsBySkill(skillString); + }, + [LoadingCriterium.ByCharacteristic] = async (o) => + { + string characString = o as string; + if(characString == null) return; + await LoadChampionsByCharacteristic(characString); + }, + [LoadingCriterium.ByClass] = async (o) => + { + if(!Enum.IsDefined(typeof(ChampionClass), o)) return; + ChampionClass champClass = (ChampionClass)o; + await LoadChampionsByClass(champClass); + }, + }; + } + + private async Task LoadChampionsFunc(Func>> loader, + Func> nbReader, + LoadingCriterium criterium, + object parameter = null) + { + Champions.Clear(); + var someChampions = (await loader()).Select(c => new ChampionVM(c)).ToList(); + foreach (var cvm in someChampions) + { + Champions.Add(cvm); + } + NbChampions = await nbReader(); + currentLoadingCriterium = criterium; + currentLoadingParameter = parameter; + } + + [RelayCommand] + public async Task LoadChampions() + { + await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItems(index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItems(), + LoadingCriterium.None); + } + + [RelayCommand(CanExecute =nameof(CanLoadChampionsByName))] + public async Task LoadChampionsByName(string substring) + { + await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItemsByName(substring, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByName(substring), + LoadingCriterium.ByName, + substring); + } + private bool CanLoadChampionsByName(string substring) + => !string.IsNullOrWhiteSpace(substring); + + [RelayCommand(CanExecute =nameof(CanLoadChampionsBySkill))] + public async Task LoadChampionsBySkill(string skill) + { + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsBySkill(skill, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsBySkill(skill), + LoadingCriterium.BySkill, + skill); + } + private bool CanLoadChampionsBySkill(string substring) => !string.IsNullOrWhiteSpace(substring); + + [RelayCommand(CanExecute = nameof(CanLoadChampionsByCharacteristic))] + public async Task LoadChampionsByCharacteristic(string characteristic) + { + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsByCharacteristic(characteristic, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByCharacteristic(characteristic), + LoadingCriterium.ByCharacteristic, + characteristic); + } + + private bool CanLoadChampionsByCharacteristic(string characteristic) + => !string.IsNullOrWhiteSpace(characteristic); + + [RelayCommand] + public async Task LoadChampionsByClass(ChampionClass champClass) + { + if(champClass == ChampionClass.Unknown) + { + return; + } + await LoadChampionsFunc( + async () => await DataMgr.ChampionsMgr.GetItemsByClass(champClass, index, count, "Name"), + async () => await DataMgr.ChampionsMgr.GetNbItemsByClass(champClass), + LoadingCriterium.ByClass, + champClass); + } + + [RelayCommand(CanExecute =nameof(CanDeleteChampion))] + public async Task DeleteChampion(object champVM) + { + ChampionVM cvm = champVM as ChampionVM; + if(cvm == null || !Champions.Contains(cvm)) return false; + bool result = await DataMgr.ChampionsMgr.DeleteItem(cvm.Model); + if(result) + { + Champions.Remove(cvm); + await LoadChampions(); + } + return result; + } + bool CanDeleteChampion(object cvm) + => cvm!= null && cvm is ChampionVM && Champions.Contains(cvm); + + [ObservableProperty] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int index = 0; + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int count = 5; + + public int NbPages + { + get + { + if(Count == 0 || NbChampions == 0) + { + return 0; + } + return (NbChampions-1) / Count + 1; + } + } + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int nbChampions = 0; + + [ObservableProperty] + private ObservableCollection champions = new ObservableCollection(); + + [RelayCommand(CanExecute =nameof(CanPreviousPage))] + async Task PreviousPage() + { + if(Index > 0) + { + Index--; + await loadingMethods[currentLoadingCriterium](currentLoadingParameter); + } + } + bool CanPreviousPage() => Index > 0; + + [RelayCommand(CanExecute =nameof(CanNextPage))] + async Task NextPage() + { + if(Index < NbPages-1) + { + Index++; + await loadingMethods[currentLoadingCriterium](currentLoadingParameter); + } + } + bool CanNextPage() => Index < NbPages-1; + + + enum LoadingCriterium + { + None, + ByName, + BySkill, + ByCharacteristic, + ByClass + } + + private LoadingCriterium currentLoadingCriterium = LoadingCriterium.None; + private object currentLoadingParameter = null; + + private Dictionary> loadingMethods; + + public async Task AddChampion(ChampionVM champVM) + { + var added = await DataMgr.ChampionsMgr.AddItem(champVM.Model); + if(added != null) + { + Champions.Add(champVM); + await LoadChampions(); + } + } + + public async Task EditChampion(ChampionVM oldChampion, ChampionVM newChampion) + { + var edited = await DataMgr.ChampionsMgr.UpdateItem(oldChampion.Model, newChampion.Model); + oldChampion.Model = newChampion.Model; + if(edited != null) + { + await LoadChampions(); + } + } +} diff --git a/Sources/ViewModels/EditableChampionVM.cs b/Sources/ViewModels/EditableChampionVM.cs new file mode 100644 index 0000000..2db038b --- /dev/null +++ b/Sources/ViewModels/EditableChampionVM.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class EditableChampionVM + { + public EditableChampionVM() + { } + + public EditableChampionVM(ChampionVM championVM) + { + Name = championVM.Name; + IconBase64 = championVM.Icon; + LargeImageBase64 = championVM.Image; + Bio = championVM.Bio; + ChampionClass = championVM.Class; + foreach(var ch in championVM.Characteristics) + { + AddCharacteristic(ch.Key, ch.Value); + } + foreach(var skill in championVM.Skills) + { + Skills.Add(skill); + } + } + + [ObservableProperty] + string name; + + [ObservableProperty] + string iconBase64; + + [ObservableProperty] + string largeImageBase64; + + [ObservableProperty] + string bio; + + [ObservableProperty] + ChampionClass championClass; + + [ObservableProperty] + ObservableCollection> characteristics = new (); + + public void AddCharacteristic(string description, int value) + => Characteristics.Add(new KeyValuePair(description, value)); + + public void RemoveCharacteristic(KeyValuePair characteristic) + => Characteristics.Remove(characteristic); + + [ObservableProperty] + ObservableCollection skills = new ObservableCollection(); + + + + public ChampionVM ToChampionVM() + { + var champion = new Champion(name, championClass, iconBase64, largeImageBase64, bio); + champion.AddCharacteristics(characteristics.Select(kvp => Tuple.Create(kvp.Key, kvp.Value)).ToArray()); + foreach(var skillVM in Skills) + { + champion.AddSkill(skillVM.Model); + } + return new ChampionVM(champion); + } + } +} + diff --git a/Sources/ViewModels/EditableSkinVM.cs b/Sources/ViewModels/EditableSkinVM.cs new file mode 100644 index 0000000..b35ca24 --- /dev/null +++ b/Sources/ViewModels/EditableSkinVM.cs @@ -0,0 +1,51 @@ +using System; +using System.Reflection.PortableExecutable; +using System.Xml.Linq; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class EditableSkinVM + { + public EditableSkinVM(ChampionVM championVM) + { + champion = championVM.Model; + } + + public EditableSkinVM(SkinVM skinVM) + { + Name = skinVM.Name; + IconBase64 = skinVM.Icon; + LargeImageBase64 = skinVM.Image; + Description = skinVM.Description; + Price = skinVM.Price; + champion = skinVM.Champion; + } + + [ObservableProperty] + private string name; + + [ObservableProperty] + private string iconBase64; + + [ObservableProperty] + private string largeImageBase64; + + [ObservableProperty] + private string description; + + [ObservableProperty] + private float price; + + private Champion champion; + + public SkinVM ToSkinVM() + { + var skin = new Skin(name, champion, price, iconBase64, largeImageBase64, description); + return new SkinVM(skin); + } + } +} + diff --git a/Sources/ViewModels/SkillVM.cs b/Sources/ViewModels/SkillVM.cs new file mode 100644 index 0000000..c9c2ca1 --- /dev/null +++ b/Sources/ViewModels/SkillVM.cs @@ -0,0 +1,32 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkillVM + { + [ObservableProperty] + private Skill model; + + public SkillVM(Skill model) + { + Model = model; + } + + public string Name => Model.Name; + + public SkillType Type => Model.Type; + + public string Description + { + get => Model.Description; + set + { + SetProperty(Model.Description, value, newValue => Model.Description = newValue); + } + } + } +} + diff --git a/Sources/ViewModels/SkinVM.cs b/Sources/ViewModels/SkinVM.cs new file mode 100644 index 0000000..358ec97 --- /dev/null +++ b/Sources/ViewModels/SkinVM.cs @@ -0,0 +1,65 @@ +using System; +using System.Reflection.PortableExecutable; +using System.Security.Claims; +using CommunityToolkit.Mvvm.ComponentModel; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkinVM + { + public Skin Model + { + get => model; + set + { + model = value; + OnPropertyChanged(nameof(Name)); + OnPropertyChanged(nameof(Description)); + OnPropertyChanged(nameof(Price)); + OnPropertyChanged(nameof(Icon)); + OnPropertyChanged(nameof(Image)); + } + } + private Skin model; + + public SkinVM(Skin model) + => Model = model; + + public string Name => Model.Name; + + public string Description + { + get => Model.Description; + set => SetProperty(Model.Description, value, newValue => Model.Description = newValue); + } + + public float Price + { + get => Model.Price; + set => SetProperty(Model.Price, value, newValue => Model.Price = newValue); + } + + public string Icon + { + get => Model.Icon; + set + { + SetProperty(Model.Icon, value, newIcon => Model.Icon = newIcon); + } + } + + public string Image + { + get => Model.Image.Base64; + set + { + SetProperty(Model.Image.Base64, value, newImage => Model.Image.Base64 = newImage); + } + } + + public Champion Champion => Model.Champion; + } +} + diff --git a/Sources/ViewModels/SkinsMgrVM.cs b/Sources/ViewModels/SkinsMgrVM.cs new file mode 100644 index 0000000..c51a6cf --- /dev/null +++ b/Sources/ViewModels/SkinsMgrVM.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Model; + +namespace ViewModels +{ + [ObservableObject] + public partial class SkinsMgrVM + { + internal IDataManager DataMgr { get; set; } + + [ObservableProperty] + private ChampionVM champion; + + public SkinsMgrVM(IDataManager dataManager) + { + DataMgr = dataManager; + } + + [ObservableProperty] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int index = 0; + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int count = 5; + + public int NbPages + { + get + { + if(Count == 0 || NbSkins == 0) + { + return 0; + } + return (NbSkins-1) / Count + 1; + } + } + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(NbPages))] + [NotifyCanExecuteChangedFor(nameof(NextPageCommand))] + [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))] + private int nbSkins = 0; + + [ObservableProperty] + private ObservableCollection skins = new ObservableCollection(); + + [RelayCommand] + async Task LoadSkins() + { + Skins.Clear(); + IEnumerable skins; + if(Champion != null) + { + skins = await DataMgr.SkinsMgr.GetItemsByChampion(Champion.Model, Index, Count,"Name"); + + } + else + { + skins = await DataMgr.SkinsMgr.GetItems(Index, Count, "Name"); + } + + foreach(var skin in skins) + { + if(skin != null) + Skins.Add(new SkinVM(skin)); + } + } + + [RelayCommand(CanExecute =nameof(CanPreviousPage))] + async Task PreviousPage() + { + if(Index > 0) + { + Index--; + await LoadSkins(); + } + } + bool CanPreviousPage() => Index > 0; + + [RelayCommand(CanExecute =nameof(CanNextPage))] + async Task NextPage() + { + if(Index < NbPages-1) + { + Index++; + await LoadSkins(); + } + } + bool CanNextPage() => Index < NbPages-1; + + [RelayCommand(CanExecute =nameof(CanDeleteSkin))] + public async Task DeleteSkin(object skinVM) + { + SkinVM svm = skinVM as SkinVM; + if(svm == null || !Skins.Contains(svm)) return false; + bool result = await DataMgr.SkinsMgr.DeleteItem(svm.Model); + if(result) + { + Skins.Remove(svm); + await LoadSkins(); + } + return result; + } + bool CanDeleteSkin(object svm) + => svm!= null && svm is SkinVM && Skins.Contains(svm); + + public async Task AddSkin(SkinVM skinVM) + { + var added = await DataMgr.SkinsMgr.AddItem(skinVM.Model); + if(added != null) + { + Skins.Add(skinVM); + await LoadSkins(); + } + } + + public async Task EditSkin(SkinVM oldSkin, SkinVM newSkin) + { + var edited = await DataMgr.SkinsMgr.UpdateItem(oldSkin.Model, newSkin.Model); + oldSkin.Model = newSkin.Model; + if(edited != null) + { + await LoadSkins(); + } + } + } +} + diff --git a/Sources/ViewModels/ViewModels.csproj b/Sources/ViewModels/ViewModels.csproj new file mode 100644 index 0000000..9110454 --- /dev/null +++ b/Sources/ViewModels/ViewModels.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + enable + enable + true + + + + + + + + +