diff --git a/critterfolio/CritterFolio/CritterFolio/App.axaml.cs b/critterfolio/CritterFolio/CritterFolio/App.axaml.cs
index 093ec86..b10e75e 100644
--- a/critterfolio/CritterFolio/CritterFolio/App.axaml.cs
+++ b/critterfolio/CritterFolio/CritterFolio/App.axaml.cs
@@ -1,3 +1,4 @@
+using System.IO;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
@@ -37,6 +38,8 @@ public partial class App : Application
}
// Other init stuff here
+ Directory.CreateDirectory(Sys.UserDataPath);
+ Directory.CreateDirectory(Path.Combine(Sys.UserDataPath, "ImageCache"));
base.OnFrameworkInitializationCompleted();
diff --git a/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml b/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml
index 6d5166b..b042639 100644
--- a/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml
+++ b/critterfolio/CritterFolio/CritterFolio/Controls/ProfileButton.axaml
@@ -11,7 +11,7 @@
VerticalContentAlignment="Center"
x:Name="MainButton">
-
+
diff --git a/critterfolio/CritterFolio/CritterFolio/DataModels/Document.cs b/critterfolio/CritterFolio/CritterFolio/DataModels/Document.cs
index aa0802a..320d4f2 100644
--- a/critterfolio/CritterFolio/CritterFolio/DataModels/Document.cs
+++ b/critterfolio/CritterFolio/CritterFolio/DataModels/Document.cs
@@ -7,6 +7,7 @@ public class Document
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
-
- public string Name { get; set; }
+ public int CritterId { get; set; }
+ public string Name { get; set; } = "Document";
+ public string Description { get; set; } = "A Document";
}
\ No newline at end of file
diff --git a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml
index a4e5fb0..6ef1bbf 100644
--- a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml
+++ b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml
@@ -7,6 +7,7 @@
+
@@ -27,6 +28,13 @@
+
+
+
+
+
+
+
diff --git a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs
index 23c6d8e..4d4658d 100644
--- a/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs
+++ b/critterfolio/CritterFolio/CritterFolio/Pages/CritterPage.axaml.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Avalonia;
@@ -7,6 +8,8 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CritterFolio.DataModels;
using CritterFolio.Services;
@@ -16,6 +19,7 @@ namespace CritterFolio.Pages;
public partial class CritterPage : Page
{
private Critter? _critter;
+ private List _critterDisplays = [];
public CritterPage()
{
@@ -25,32 +29,38 @@ public partial class CritterPage : Page
public void Init(Critter critter)
{
_critter = critter;
-
- UpdateInfo();
+
+ PfpButton.Click += OpenFileButton_Clicked;
}
- public override void Refresh()
+ public override async void Refresh()
{
base.Refresh();
CreateHeaderButtons();
GenderOption.ItemsSource = Enum.GetNames(typeof(Gender));
-
- LoadComboItemsAsync();
+
+ await UpdateInfo();
}
- private async void LoadComboItemsAsync()
+ private async Task LoadComboItemsAsync()
{
+ _critterDisplays.Clear();
+ _critterDisplays.Add(new CritterComboBoxDisplay(0, "Not set"));
+
try
{
var allCritters = await DatabaseService.GetAllCritters();
- var allCritterIds = allCritters.Select(c => c.Id).ToList();
+
+ foreach (var critter in allCritters)
+ {
+ if (critter.Id == _critter?.Id) continue;
+ _critterDisplays.Add(new CritterComboBoxDisplay(critter.Id, critter.Name));
+ }
await Dispatcher.UIThread.InvokeAsync(() =>
{
- FatherPicker.ItemsSource = allCritterIds;
- MotherPicker.ItemsSource = allCritterIds;
-
- UpdateInfo();
+ FatherPicker.ItemsSource = _critterDisplays;
+ MotherPicker.ItemsSource = _critterDisplays;
});
}
catch (Exception ex)
@@ -59,15 +69,64 @@ public partial class CritterPage : Page
}
}
- private void UpdateInfo()
+ private async Task UpdateInfo()
{
+ if (_critter is null) return;
+
Sys.Navigation?.SetTitle(_critter.Name);
+
+ await LoadComboItemsAsync();
NameBox.Text = _critter.Name;
GenderOption.SelectedItem = Enum.GetName(typeof(Gender), _critter.Gender);
BirthdayPicker.SelectedDate = _critter.DateOfBirth;
- MotherPicker.SelectedItem = _critter.FatherId;
- FatherPicker.SelectedItem = _critter.FatherId;
+
+ if (_critter.FatherId != 0)
+ {
+ var father = _critterDisplays.FirstOrDefault(c => c.Id == _critter.FatherId);
+ if (father is null)
+ {
+ Logger.LogToFile($"Couldn't find father id: {_critter.FatherId}");
+ await DialogHelper.ShowMessage($"ERROR: Couldn't find FatherID: {_critter.FatherId}");
+ return;
+ }
+ FatherPicker.SelectedItem = father;
+ }
+ else
+ {
+ FatherPicker.SelectedItem = _critterDisplays.FirstOrDefault(c => c.Id == 0);
+ }
+
+ if (_critter.MotherId != 0)
+ {
+ var mother = _critterDisplays.FirstOrDefault(c => c.Id == _critter.MotherId);
+ if (mother is null)
+ {
+ Logger.LogToFile($"[ERROR] Couldn't find MotherId: {_critter.MotherId}");
+ await DialogHelper.ShowMessage($"ERROR: Couldn't find MotherId: {_critter.MotherId}");
+ return;
+ }
+ MotherPicker.SelectedItem = mother;
+ }
+ else
+ {
+ MotherPicker.SelectedItem = _critterDisplays.FirstOrDefault(c => c.Id == 0);
+ }
+
+ NotesBox.Text = _critter.Notes;
+
+ if (!string.IsNullOrWhiteSpace(_critter.ProfileImagePath))
+ {
+ try
+ {
+ var bmp = new Bitmap(_critter.ProfileImagePath);
+ ProfImage.Source = bmp;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Pfp image for {_critter.Id} was moved, deleted, or is corrupt.");
+ }
+ }
}
private void CreateHeaderButtons()
@@ -86,14 +145,13 @@ public partial class CritterPage : Page
Classes = { "headerBttn" },
Content = "\ue4a6"
};
- delBttn.Foreground = new SolidColorBrush(Colors.DarkRed);
+ delBttn.Foreground = new SolidColorBrush(Colors.Red);
delBttn.Click += DeleteButtonClicked;
Sys.Navigation?.AddHeaderButton(delBttn);
}
private async void DeleteButtonClicked(object? sender, RoutedEventArgs args)
{
-
try
{
var result = await DialogHelper.ShowConfirmationDialog("Are you sure you want to delete this critter?");
@@ -125,7 +183,7 @@ public partial class CritterPage : Page
}
await DatabaseService.UpdateCritter(_critter);
- UpdateInfo();
+ await UpdateInfo();
await DialogHelper.ShowMessage($"Critter '{_critter.Name}' saved!");
}
@@ -164,28 +222,81 @@ public partial class CritterPage : Page
errString += "Birthday is invalid somehow. Please report this to the developer\n";
}
- // Dont need to validate these yet, as they are not required
- // // Father ID validation
- // if (FatherPicker.SelectedItem is int fatherId)
- // {
- // _critter.FatherId = fatherId;
- // }
- // else
- // {
- // errString += "FatherId is null or invalid somehow. Please report this to the developer\n";
- // }
- //
- // // Mother ID validation
- // if (MotherPicker.SelectedItem is int motherId)
- // {
- // _critter.MotherId = motherId;
- // }
- // else
- // {
- // errString += "MotherId is null or invalid somehow. Please report this to the developer\n";
- // }
-
+ // TODO: Change the way that fatherid and motherid work, it should show names, not the ids, but still link back to the id
+ // Father ID validation
+ if (FatherPicker.SelectedItem is CritterComboBoxDisplay father)
+ {
+ var id = _critterDisplays.FirstOrDefault(d => d.Id == father.Id);
+ _critter.FatherId = id?.Id ?? 0;
+ }
+ else
+ {
+ _critter.FatherId = 0;
+ }
+
+ // Mother ID validation
+ if (MotherPicker.SelectedItem is CritterComboBoxDisplay mother)
+ {
+ var id = _critterDisplays.FirstOrDefault(d => d.Id == mother.Id);
+ _critter.MotherId = id?.Id ?? 0;
+ }
+ else
+ {
+ _critter.MotherId = 0;
+ }
+
+ if (_critter.MotherId == _critter.FatherId && _critter.MotherId > 0 && _critter.FatherId > 0)
+ {
+ errString += "Mother and Father cannot be the same";
+ }
+
+ _critter.Notes = NotesBox.Text ?? "";
+
return errString != "" ? (false, errString) : (true, "No errors");
}
+ private class CritterComboBoxDisplay(int id, string name)
+ {
+ public int Id { get; set; } = id;
+ public string Name { get; set; } = name;
+
+ public override string ToString() => Name;
+ }
+
+ private async void OpenFileButton_Clicked(object? sender, RoutedEventArgs args)
+ {
+ var topLevel = TopLevel.GetTopLevel(this);
+
+ var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
+ {
+ Title = "Open Image File",
+ AllowMultiple = false,
+ FileTypeFilter = [new FilePickerFileType("image"){Patterns = ["*.png", "*.jpg", "*.jpeg"]}]
+ });
+
+ if (files.Count == 0) return;
+
+ var file = files[0];
+
+ try
+ {
+
+ await using var stream = await file.OpenReadAsync();
+ // using var streamReader = new StreamReader(stream);
+ // var fileContent = await streamReader.ReadToEndAsync();
+
+ var bmp = new Bitmap(stream);
+ var path = Path.Combine(Sys.UserDataPath, "ImageCache", $"{_critter.Id}-{_critter.Name}.jpg");
+ bmp.Save(path);
+ _critter.ProfileImagePath = path;
+ await UpdateInfo();
+ }
+ catch (Exception e)
+ {
+ await DialogHelper.ShowMessage(e.ToString());
+ }
+
+
+ }
+
}
\ No newline at end of file