Notes and Profile Pictures are now working, and Mother and Father selections are no longer just Ids
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.IO;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Data.Core;
|
using Avalonia.Data.Core;
|
||||||
@@ -37,6 +38,8 @@ public partial class App : Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Other init stuff here
|
// Other init stuff here
|
||||||
|
Directory.CreateDirectory(Sys.UserDataPath);
|
||||||
|
Directory.CreateDirectory(Path.Combine(Sys.UserDataPath, "ImageCache"));
|
||||||
|
|
||||||
|
|
||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
VerticalContentAlignment="Center"
|
VerticalContentAlignment="Center"
|
||||||
x:Name="MainButton">
|
x:Name="MainButton">
|
||||||
<Grid ColumnDefinitions="Auto, *, Auto">
|
<Grid ColumnDefinitions="Auto, *, Auto">
|
||||||
<Image x:Name="ProfileImage" Grid.Column="0" Width="80" Height="80" Stretch="UniformToFill" Source="avares://CritterFolio/Assets/Icon.png" />
|
<Image x:Name="ProfileImage" Grid.Column="0" Width="75" Height="75" Stretch="UniformToFill" Source="avares://CritterFolio/Assets/Icon.png" />
|
||||||
<Label x:Name="ProfileNameLabel" Grid.Column="1" VerticalAlignment="Center" FontSize="18" Margin="20, 0" />
|
<Label x:Name="ProfileNameLabel" Grid.Column="1" VerticalAlignment="Center" FontSize="18" Margin="20, 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ public class Document
|
|||||||
{
|
{
|
||||||
[PrimaryKey, AutoIncrement]
|
[PrimaryKey, AutoIncrement]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
public int CritterId { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; } = "Document";
|
||||||
|
public string Description { get; set; } = "A Document";
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
<ScrollViewer HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
<ScrollViewer HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
<StackPanel Spacing="10">
|
<StackPanel Spacing="10">
|
||||||
<Label Classes="heading1">Info</Label>
|
<Label Classes="heading1">Info</Label>
|
||||||
|
<Image x:Name="ProfImage" Width="150" Height="150" Stretch="UniformToFill" Source="avares://CritterFolio/Assets/Icon.png" />
|
||||||
<StackPanel HorizontalAlignment="Stretch">
|
<StackPanel HorizontalAlignment="Stretch">
|
||||||
<Label VerticalAlignment="Center">Name: </Label>
|
<Label VerticalAlignment="Center">Name: </Label>
|
||||||
<TextBox x:Name="NameBox" />
|
<TextBox x:Name="NameBox" />
|
||||||
@@ -27,6 +28,13 @@
|
|||||||
<Label VerticalAlignment="Center">Father: </Label>
|
<Label VerticalAlignment="Center">Father: </Label>
|
||||||
<ComboBox x:Name="FatherPicker" />
|
<ComboBox x:Name="FatherPicker" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel HorizontalAlignment="Stretch">
|
||||||
|
<Label VerticalAlignment="Center">Notes: </Label>
|
||||||
|
<TextBox x:Name="NotesBox" MinHeight="100" AcceptsReturn="True" TextWrapping="Wrap" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel>
|
||||||
|
<Button x:Name="PfpButton">Choose Profile Picture</Button>
|
||||||
|
</StackPanel>
|
||||||
<!-- <Button x:Name="AddButton" Classes="icon" HorizontalAlignment="Stretch"></Button> -->
|
<!-- <Button x:Name="AddButton" Classes="icon" HorizontalAlignment="Stretch"></Button> -->
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
@@ -7,6 +8,8 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using CritterFolio.DataModels;
|
using CritterFolio.DataModels;
|
||||||
using CritterFolio.Services;
|
using CritterFolio.Services;
|
||||||
@@ -16,6 +19,7 @@ namespace CritterFolio.Pages;
|
|||||||
public partial class CritterPage : Page
|
public partial class CritterPage : Page
|
||||||
{
|
{
|
||||||
private Critter? _critter;
|
private Critter? _critter;
|
||||||
|
private List<CritterComboBoxDisplay> _critterDisplays = [];
|
||||||
|
|
||||||
public CritterPage()
|
public CritterPage()
|
||||||
{
|
{
|
||||||
@@ -26,31 +30,37 @@ public partial class CritterPage : Page
|
|||||||
{
|
{
|
||||||
_critter = critter;
|
_critter = critter;
|
||||||
|
|
||||||
UpdateInfo();
|
PfpButton.Click += OpenFileButton_Clicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Refresh()
|
public override async void Refresh()
|
||||||
{
|
{
|
||||||
base.Refresh();
|
base.Refresh();
|
||||||
CreateHeaderButtons();
|
CreateHeaderButtons();
|
||||||
GenderOption.ItemsSource = Enum.GetNames(typeof(Gender));
|
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
|
try
|
||||||
{
|
{
|
||||||
var allCritters = await DatabaseService.GetAllCritters();
|
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(() =>
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
FatherPicker.ItemsSource = allCritterIds;
|
FatherPicker.ItemsSource = _critterDisplays;
|
||||||
MotherPicker.ItemsSource = allCritterIds;
|
MotherPicker.ItemsSource = _critterDisplays;
|
||||||
|
|
||||||
UpdateInfo();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
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);
|
Sys.Navigation?.SetTitle(_critter.Name);
|
||||||
|
|
||||||
|
await LoadComboItemsAsync();
|
||||||
|
|
||||||
NameBox.Text = _critter.Name;
|
NameBox.Text = _critter.Name;
|
||||||
GenderOption.SelectedItem = Enum.GetName(typeof(Gender), _critter.Gender);
|
GenderOption.SelectedItem = Enum.GetName(typeof(Gender), _critter.Gender);
|
||||||
BirthdayPicker.SelectedDate = _critter.DateOfBirth;
|
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()
|
private void CreateHeaderButtons()
|
||||||
@@ -86,14 +145,13 @@ public partial class CritterPage : Page
|
|||||||
Classes = { "headerBttn" },
|
Classes = { "headerBttn" },
|
||||||
Content = "\ue4a6"
|
Content = "\ue4a6"
|
||||||
};
|
};
|
||||||
delBttn.Foreground = new SolidColorBrush(Colors.DarkRed);
|
delBttn.Foreground = new SolidColorBrush(Colors.Red);
|
||||||
delBttn.Click += DeleteButtonClicked;
|
delBttn.Click += DeleteButtonClicked;
|
||||||
Sys.Navigation?.AddHeaderButton(delBttn);
|
Sys.Navigation?.AddHeaderButton(delBttn);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void DeleteButtonClicked(object? sender, RoutedEventArgs args)
|
private async void DeleteButtonClicked(object? sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await DialogHelper.ShowConfirmationDialog("Are you sure you want to delete this critter?");
|
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);
|
await DatabaseService.UpdateCritter(_critter);
|
||||||
UpdateInfo();
|
await UpdateInfo();
|
||||||
|
|
||||||
await DialogHelper.ShowMessage($"Critter '{_critter.Name}' saved!");
|
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";
|
errString += "Birthday is invalid somehow. Please report this to the developer\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dont need to validate these yet, as they are not required
|
// 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
|
// Father ID validation
|
||||||
// if (FatherPicker.SelectedItem is int fatherId)
|
if (FatherPicker.SelectedItem is CritterComboBoxDisplay father)
|
||||||
// {
|
{
|
||||||
// _critter.FatherId = fatherId;
|
var id = _critterDisplays.FirstOrDefault(d => d.Id == father.Id);
|
||||||
// }
|
_critter.FatherId = id?.Id ?? 0;
|
||||||
// else
|
}
|
||||||
// {
|
else
|
||||||
// errString += "FatherId is null or invalid somehow. Please report this to the developer\n";
|
{
|
||||||
// }
|
_critter.FatherId = 0;
|
||||||
//
|
}
|
||||||
// // Mother ID validation
|
|
||||||
// if (MotherPicker.SelectedItem is int motherId)
|
// Mother ID validation
|
||||||
// {
|
if (MotherPicker.SelectedItem is CritterComboBoxDisplay mother)
|
||||||
// _critter.MotherId = motherId;
|
{
|
||||||
// }
|
var id = _critterDisplays.FirstOrDefault(d => d.Id == mother.Id);
|
||||||
// else
|
_critter.MotherId = id?.Id ?? 0;
|
||||||
// {
|
}
|
||||||
// errString += "MotherId is null or invalid somehow. Please report this to the developer\n";
|
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");
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user