Remove sqlite base64 contact store from AccountContact.

This commit is contained in:
Burak Kaan Köse
2026-03-07 11:43:56 +01:00
parent 8e8b123aa6
commit 09f1cee3a5
18 changed files with 136 additions and 103 deletions
@@ -18,13 +18,13 @@ namespace Wino.Controls;
/// <summary>
/// Contact avatar control built on top of PersonPicture.
/// Priority:
/// 1) AccountContact/Base64 picture
/// 1) AccountContact file-based picture
/// 2) Gravatar thumbnail (if enabled)
/// 3) Initials from display name fallback
/// </summary>
public sealed partial class ImagePreviewControl : PersonPicture
{
private sealed record RefreshSnapshot(string DisplayName, string Address, Guid? ContactPictureFileId, string Base64Picture);
private sealed record RefreshSnapshot(string DisplayName, string Address, Guid? ContactPictureFileId);
private static readonly TimeSpan RefreshDebounceDuration = TimeSpan.FromMilliseconds(40);
@@ -109,7 +109,7 @@ public sealed partial class ImagePreviewControl : PersonPicture
{
// Refresh only for fields that affect avatar image or initials.
if (string.IsNullOrEmpty(e.PropertyName)
|| e.PropertyName == nameof(IMailItemDisplayInformation.Base64ContactPicture)
|| e.PropertyName == nameof(IMailItemDisplayInformation.ContactPictureFileId)
|| e.PropertyName == nameof(IMailItemDisplayInformation.SenderContact)
|| e.PropertyName == nameof(IMailItemDisplayInformation.FromName)
|| e.PropertyName == nameof(IMailItemDisplayInformation.FromAddress)
@@ -222,18 +222,7 @@ public sealed partial class ImagePreviewControl : PersonPicture
}
}
// 2) Legacy base64 contact picture (used until migration completes or for fallback).
if (!string.IsNullOrWhiteSpace(snapshot.Base64Picture))
{
var localBitmap = await CreateBitmapFromBase64Async(snapshot.Base64Picture, cancellationToken).ConfigureAwait(false);
if (localBitmap != null)
{
await ApplyProfilePictureAsync(localBitmap, refreshVersion, cancellationToken).ConfigureAwait(false);
return;
}
}
// 3) Gravatar lookup through thumbnail service (if enabled).
// 2) Gravatar lookup through thumbnail service (if enabled).
if (_preferencesService?.IsGravatarEnabled == true &&
_thumbnailService != null &&
!string.IsNullOrWhiteSpace(snapshot.Address) &&
@@ -254,7 +243,7 @@ public sealed partial class ImagePreviewControl : PersonPicture
}
}
// 4) Initials fallback is already in place via DisplayName + ProfilePicture = null.
// 3) Initials fallback is already in place via DisplayName + ProfilePicture = null.
}
catch (OperationCanceledException)
{
@@ -276,10 +265,11 @@ public sealed partial class ImagePreviewControl : PersonPicture
var address = ResolveAddress();
var displayName = ResolveDisplayName(address);
var base64Picture = ResolveBase64Picture();
var contactPictureFileId = PreviewContact?.ContactPictureFileId ?? MailItemInformation?.SenderContact?.ContactPictureFileId;
var contactPictureFileId = PreviewContact?.ContactPictureFileId
?? MailItemInformation?.SenderContact?.ContactPictureFileId
?? MailItemInformation?.ContactPictureFileId;
return new RefreshSnapshot(displayName, address, contactPictureFileId, base64Picture);
return new RefreshSnapshot(displayName, address, contactPictureFileId);
}).ConfigureAwait(false);
}
@@ -321,20 +311,6 @@ public sealed partial class ImagePreviewControl : PersonPicture
return resolvedAddress.Trim();
}
private string ResolveBase64Picture()
{
if (!string.IsNullOrWhiteSpace(PreviewContact?.Base64ContactPicture))
return PreviewContact.Base64ContactPicture;
if (!string.IsNullOrWhiteSpace(MailItemInformation?.SenderContact?.Base64ContactPicture))
return MailItemInformation.SenderContact.Base64ContactPicture;
if (!string.IsNullOrWhiteSpace(MailItemInformation?.Base64ContactPicture))
return MailItemInformation.Base64ContactPicture;
return string.Empty;
}
private async Task ApplyInitialVisualStateAsync(string displayName, long refreshVersion, CancellationToken cancellationToken)
{
await ExecuteOnUiThreadAsync(() =>
@@ -2,6 +2,7 @@
x:Class="Wino.Dialogs.ContactEditDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Wino.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -52,7 +53,7 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<PersonPicture
<controls:ImagePreviewControl
x:Name="ContactPhotoPersonPicture"
Grid.Column="0"
Width="64"
@@ -61,11 +61,6 @@ public sealed partial class ContactEditDialog : ContentDialog
RemovePhotoButton.Visibility = Visibility.Visible;
}
}
else if (!string.IsNullOrEmpty(_contact.Base64ContactPicture))
{
LoadContactPhotoFromBase64(_contact.Base64ContactPicture);
RemovePhotoButton.Visibility = Visibility.Visible;
}
else
{
ContactPhotoPersonPicture.DisplayName = _contact.Name ?? string.Empty;
@@ -101,9 +96,7 @@ public sealed partial class ContactEditDialog : ContentDialog
}
else
{
// Fallback to legacy base64 when service is unavailable (e.g. design-time).
_contact.Base64ContactPicture = Convert.ToBase64String(file.Data);
LoadContactPhotoFromBase64(_contact.Base64ContactPicture);
LoadContactPhoto(file.Data);
}
RemovePhotoButton.Visibility = Visibility.Visible;
@@ -121,7 +114,6 @@ public sealed partial class ContactEditDialog : ContentDialog
_ = _contactPictureFileService.DeleteContactPictureAsync(_contact.ContactPictureFileId.Value);
_contact.ContactPictureFileId = null;
_contact.Base64ContactPicture = null;
ContactPhotoPersonPicture.ProfilePicture = null;
ContactPhotoPersonPicture.DisplayName = ContactNameTextBox.Text;
RemovePhotoButton.Visibility = Visibility.Collapsed;
@@ -143,11 +135,10 @@ public sealed partial class ContactEditDialog : ContentDialog
}
}
private void LoadContactPhotoFromBase64(string base64String)
private void LoadContactPhoto(byte[] imageBytes)
{
try
{
var imageBytes = Convert.FromBase64String(base64String);
using var stream = new MemoryStream(imageBytes);
var bitmap = new BitmapImage();
bitmap.SetSource(stream.AsRandomAccessStream());
@@ -14,6 +14,7 @@
xmlns:local="using:Wino.Calendar.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Wino.Controls"
xmlns:shared="using:Wino.Core.Domain.Entities.Shared"
mc:Ignorable="d">
@@ -338,10 +339,10 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<muxc:PersonPicture
<controls:ImagePreviewControl
Width="46"
Height="46"
DisplayName="BK" />
DisplayNameOverride="{x:Bind ViewModel.DisplayDetailsCalendarItemViewModel.CalendarItem.OrganizerDisplayName, Mode=OneWay}" />
<StackPanel
Grid.Column="1"
@@ -8,6 +8,7 @@
xmlns:calendarHelpers="using:Wino.Calendar.Helpers"
xmlns:calendarViewModels="using:Wino.Calendar.ViewModels"
xmlns:coreControls="using:Wino.Mail.WinUI.Controls"
xmlns:controls="using:Wino.Controls"
xmlns:ctControls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="using:Wino.Calendar.ViewModels.Data"
@@ -453,10 +454,11 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<PersonPicture
<controls:ImagePreviewControl
Width="40"
Height="40"
DisplayName="{x:Bind Name}" />
Address="{x:Bind Email}"
DisplayNameOverride="{x:Bind Name}" />
<Grid Grid.Column="1" RowSpacing="4">
<Grid.RowDefinitions>
+2 -2
View File
@@ -43,7 +43,7 @@
</Grid.ContextFlyout>-->
<Viewbox Width="24">
<PersonPicture DisplayName="{x:Bind Name, Mode=OneTime}" />
<controls:ImagePreviewControl PreviewContact="{x:Bind}" />
</Viewbox>
<TextBlock
@@ -59,7 +59,7 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<PersonPicture DisplayName="{x:Bind Name, Mode=OneTime}" />
<controls:ImagePreviewControl PreviewContact="{x:Bind}" />
<TextBlock Grid.Column="1">
<Run FontWeight="SemiBold" Text="{x:Bind Name}" /><LineBreak /><Run Text="{x:Bind Address}" />
</TextBlock>
@@ -151,7 +151,10 @@
</Page.Resources>
<!-- Attachments and WebView2 -->
<Grid x:Name="RendererGridFrame" RowSpacing="7">
<Grid
x:Name="RendererGridFrame"
Margin="0,2,0,0"
RowSpacing="7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />