Contacts, thread animation and image preview control improvements.

This commit is contained in:
Burak Kaan Köse
2026-02-09 22:39:30 +01:00
parent e559a79506
commit 0999c71578
26 changed files with 1636 additions and 756 deletions
+12 -12
View File
@@ -5,14 +5,13 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Edit Contact"
HorizontalContentAlignment="Stretch"
DefaultButton="Primary"
IsPrimaryButtonEnabled="True"
PrimaryButtonClick="SaveClicked"
PrimaryButtonText="Save"
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Save, Mode=OneTime}"
SecondaryButtonClick="CancelClicked"
SecondaryButtonText="Cancel"
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel, Mode=OneTime}"
Style="{StaticResource WinoDialogStyle}"
mc:Ignorable="d">
@@ -24,15 +23,15 @@
<!-- Contact Name -->
<TextBox
x:Name="ContactNameTextBox"
Header="Name"
PlaceholderText="Contact name"
Header="{x:Bind domain:Translator.ContactEditDialog_NameHeader, Mode=OneTime}"
PlaceholderText="{x:Bind domain:Translator.ContactEditDialog_NamePlaceholder, Mode=OneTime}"
TextChanged="ValidateInput" />
<!-- Email Address -->
<TextBox
x:Name="EmailAddressTextBox"
Header="Email Address"
PlaceholderText="contact@example.com"
Header="{x:Bind domain:Translator.ContactEditDialog_EmailHeader, Mode=OneTime}"
PlaceholderText="{x:Bind domain:Translator.ContactEditDialog_EmailPlaceholder, Mode=OneTime}"
TextChanged="ValidateInput" />
<!-- Contact Photo -->
@@ -40,7 +39,7 @@
<TextBlock
Margin="0,0,0,8"
FontWeight="SemiBold"
Text="Photo" />
Text="{x:Bind domain:Translator.ContactEditDialog_PhotoSection, Mode=OneTime}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -61,11 +60,12 @@
<Button
x:Name="ChoosePhotoButton"
Click="ChoosePhotoClicked"
Content="Choose Photo" />
Content="{x:Bind domain:Translator.ContactEditDialog_ChoosePhoto, Mode=OneTime}" />
<Button
x:Name="RemovePhotoButton"
Click="RemovePhotoClicked"
Content="Remove Photo" />
Content="{x:Bind domain:Translator.ContactEditDialog_RemovePhoto, Mode=OneTime}"
Visibility="Collapsed" />
</StackPanel>
</Grid>
</StackPanel>
@@ -79,7 +79,7 @@
Visibility="Collapsed">
<TextBlock
Foreground="{ThemeResource TextOnAccentFillColorPrimaryBrush}"
Text="This is a root contact and cannot be deleted."
Text="{x:Bind domain:Translator.ContactEditDialog_RootContactInfo, Mode=OneTime}"
TextWrapping="Wrap" />
</Border>
@@ -91,7 +91,7 @@
Visibility="Collapsed">
<TextBlock
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
Text="This contact has been manually modified."
Text="{x:Bind domain:Translator.ContactEditDialog_OverriddenContactInfo, Mode=OneTime}"
TextWrapping="Wrap" />
</Border>
</StackPanel>
@@ -1,6 +1,9 @@
using System;
using System.IO;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
@@ -10,16 +13,20 @@ public sealed partial class ContactEditDialog : ContentDialog
{
private AccountContact _contact;
private IDialogServiceBase? _dialogService;
private bool _isEditMode;
public AccountContact Contact => _contact;
public ContactEditDialog(AccountContact? contact = null, IDialogServiceBase? dialogService = null)
{
InitializeComponent();
_contact = contact ?? new AccountContact();
_dialogService = dialogService;
_isEditMode = contact != null && !string.IsNullOrEmpty(contact.Address);
Title = _isEditMode ? Translator.ContactEditDialog_Title : Translator.ContactEditDialog_AddTitle;
LoadContactData();
ValidateInput();
}
@@ -31,67 +38,109 @@ public sealed partial class ContactEditDialog : ContentDialog
ContactNameTextBox.Text = _contact.Name ?? string.Empty;
EmailAddressTextBox.Text = _contact.Address ?? string.Empty;
// Show info badges
// Disable email editing for existing contacts (Address is PK).
EmailAddressTextBox.IsEnabled = !_isEditMode;
if (_contact.IsRootContact)
{
RootContactInfoBorder.Visibility = Visibility.Visible;
}
if (_contact.IsOverridden)
{
OverriddenContactInfoBorder.Visibility = Visibility.Visible;
// Load existing photo.
if (!string.IsNullOrEmpty(_contact.Base64ContactPicture))
{
LoadContactPhoto(_contact.Base64ContactPicture);
RemovePhotoButton.Visibility = Visibility.Visible;
}
else
{
ContactPhotoPersonPicture.DisplayName = _contact.Name ?? string.Empty;
RemovePhotoButton.Visibility = Visibility.Collapsed;
}
}
}
private void ChoosePhotoClicked(object sender, RoutedEventArgs e)
private async void ChoosePhotoClicked(object sender, RoutedEventArgs e)
{
// TODO: Implement photo picker
if (_dialogService == null) return;
try
{
var files = await _dialogService.PickFilesAsync(".png", ".jpg", ".jpeg");
if (files?.Count > 0)
{
var file = files[0];
var base64 = Convert.ToBase64String(file.Data);
_contact.Base64ContactPicture = base64;
LoadContactPhoto(base64);
RemovePhotoButton.Visibility = Visibility.Visible;
}
}
catch (Exception)
{
// Failed to pick photo, ignore.
}
}
private void RemovePhotoClicked(object sender, RoutedEventArgs e)
{
_contact.Base64ContactPicture = null;
ContactPhotoPersonPicture.ProfilePicture = null;
ContactPhotoPersonPicture.DisplayName = ContactNameTextBox.Text;
RemovePhotoButton.Visibility = Visibility.Collapsed;
}
private void LoadContactPhoto(string base64String)
{
try
{
var imageBytes = Convert.FromBase64String(base64String);
using var stream = new MemoryStream(imageBytes);
var bitmap = new BitmapImage();
bitmap.SetSource(stream.AsRandomAccessStream());
ContactPhotoPersonPicture.ProfilePicture = bitmap;
}
catch
{
// Failed to load image, ignore.
}
}
private void ValidateInput(object? sender = null, TextChangedEventArgs? e = null)
{
var hasName = !string.IsNullOrWhiteSpace(ContactNameTextBox.Text);
var hasEmail = !string.IsNullOrWhiteSpace(EmailAddressTextBox.Text);
var isValidEmail = hasEmail && IsValidEmail(EmailAddressTextBox.Text);
IsPrimaryButtonEnabled = hasName && isValidEmail;
}
var isValidEmail = hasEmail && EmailValidation.EmailValidator.Validate(EmailAddressTextBox.Text);
private bool IsValidEmail(string email)
{
try
if (_isEditMode)
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
// In edit mode, only name is required (email is locked).
IsPrimaryButtonEnabled = hasName;
}
catch
else
{
return false;
// In create mode, both name and valid email are required.
IsPrimaryButtonEnabled = hasName && isValidEmail;
}
}
private void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
// Update contact data
_contact.Name = ContactNameTextBox.Text?.Trim();
_contact.Address = EmailAddressTextBox.Text?.Trim();
// Mark as overridden if this was a user edit
if (!string.IsNullOrEmpty(_contact.Address))
{
if (!_isEditMode)
_contact.Address = EmailAddressTextBox.Text?.Trim();
// Mark as overridden if this was a user edit of an existing contact.
if (_isEditMode)
_contact.IsOverridden = true;
}
}
private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
// Nothing to do, dialog will close
// Nothing to do, dialog will close.
}
}
}